tests.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. from __future__ import unicode_literals
  2. from django.db import models
  3. from django.test import SimpleTestCase, override_settings
  4. from django.utils import six
  5. class FieldDeconstructionTests(SimpleTestCase):
  6. """
  7. Tests the deconstruct() method on all core fields.
  8. """
  9. def test_name(self):
  10. """
  11. Tests the outputting of the correct name if assigned one.
  12. """
  13. # First try using a "normal" field
  14. field = models.CharField(max_length=65)
  15. name, path, args, kwargs = field.deconstruct()
  16. self.assertIsNone(name)
  17. field.set_attributes_from_name("is_awesome_test")
  18. name, path, args, kwargs = field.deconstruct()
  19. self.assertEqual(name, "is_awesome_test")
  20. self.assertIsInstance(name, six.text_type)
  21. # Now try with a ForeignKey
  22. field = models.ForeignKey("some_fake.ModelName", models.CASCADE)
  23. name, path, args, kwargs = field.deconstruct()
  24. self.assertIsNone(name)
  25. field.set_attributes_from_name("author")
  26. name, path, args, kwargs = field.deconstruct()
  27. self.assertEqual(name, "author")
  28. def test_auto_field(self):
  29. field = models.AutoField(primary_key=True)
  30. field.set_attributes_from_name("id")
  31. name, path, args, kwargs = field.deconstruct()
  32. self.assertEqual(path, "django.db.models.AutoField")
  33. self.assertEqual(args, [])
  34. self.assertEqual(kwargs, {"primary_key": True})
  35. def test_big_integer_field(self):
  36. field = models.BigIntegerField()
  37. name, path, args, kwargs = field.deconstruct()
  38. self.assertEqual(path, "django.db.models.BigIntegerField")
  39. self.assertEqual(args, [])
  40. self.assertEqual(kwargs, {})
  41. def test_boolean_field(self):
  42. field = models.BooleanField()
  43. name, path, args, kwargs = field.deconstruct()
  44. self.assertEqual(path, "django.db.models.BooleanField")
  45. self.assertEqual(args, [])
  46. self.assertEqual(kwargs, {})
  47. field = models.BooleanField(default=True)
  48. name, path, args, kwargs = field.deconstruct()
  49. self.assertEqual(path, "django.db.models.BooleanField")
  50. self.assertEqual(args, [])
  51. self.assertEqual(kwargs, {"default": True})
  52. def test_char_field(self):
  53. field = models.CharField(max_length=65)
  54. name, path, args, kwargs = field.deconstruct()
  55. self.assertEqual(path, "django.db.models.CharField")
  56. self.assertEqual(args, [])
  57. self.assertEqual(kwargs, {"max_length": 65})
  58. field = models.CharField(max_length=65, null=True, blank=True)
  59. name, path, args, kwargs = field.deconstruct()
  60. self.assertEqual(path, "django.db.models.CharField")
  61. self.assertEqual(args, [])
  62. self.assertEqual(kwargs, {"max_length": 65, "null": True, "blank": True})
  63. def test_char_field_choices(self):
  64. field = models.CharField(max_length=1, choices=(("A", "One"), ("B", "Two")))
  65. name, path, args, kwargs = field.deconstruct()
  66. self.assertEqual(path, "django.db.models.CharField")
  67. self.assertEqual(args, [])
  68. self.assertEqual(kwargs, {"choices": [("A", "One"), ("B", "Two")], "max_length": 1})
  69. def test_csi_field(self):
  70. field = models.CommaSeparatedIntegerField(max_length=100)
  71. name, path, args, kwargs = field.deconstruct()
  72. self.assertEqual(path, "django.db.models.CommaSeparatedIntegerField")
  73. self.assertEqual(args, [])
  74. self.assertEqual(kwargs, {"max_length": 100})
  75. def test_date_field(self):
  76. field = models.DateField()
  77. name, path, args, kwargs = field.deconstruct()
  78. self.assertEqual(path, "django.db.models.DateField")
  79. self.assertEqual(args, [])
  80. self.assertEqual(kwargs, {})
  81. field = models.DateField(auto_now=True)
  82. name, path, args, kwargs = field.deconstruct()
  83. self.assertEqual(path, "django.db.models.DateField")
  84. self.assertEqual(args, [])
  85. self.assertEqual(kwargs, {"auto_now": True})
  86. def test_datetime_field(self):
  87. field = models.DateTimeField()
  88. name, path, args, kwargs = field.deconstruct()
  89. self.assertEqual(path, "django.db.models.DateTimeField")
  90. self.assertEqual(args, [])
  91. self.assertEqual(kwargs, {})
  92. field = models.DateTimeField(auto_now_add=True)
  93. name, path, args, kwargs = field.deconstruct()
  94. self.assertEqual(path, "django.db.models.DateTimeField")
  95. self.assertEqual(args, [])
  96. self.assertEqual(kwargs, {"auto_now_add": True})
  97. # Bug #21785
  98. field = models.DateTimeField(auto_now=True, auto_now_add=True)
  99. name, path, args, kwargs = field.deconstruct()
  100. self.assertEqual(path, "django.db.models.DateTimeField")
  101. self.assertEqual(args, [])
  102. self.assertEqual(kwargs, {"auto_now_add": True, "auto_now": True})
  103. def test_decimal_field(self):
  104. field = models.DecimalField(max_digits=5, decimal_places=2)
  105. name, path, args, kwargs = field.deconstruct()
  106. self.assertEqual(path, "django.db.models.DecimalField")
  107. self.assertEqual(args, [])
  108. self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 2})
  109. def test_decimal_field_0_decimal_places(self):
  110. """
  111. A DecimalField with decimal_places=0 should work (#22272).
  112. """
  113. field = models.DecimalField(max_digits=5, decimal_places=0)
  114. name, path, args, kwargs = field.deconstruct()
  115. self.assertEqual(path, "django.db.models.DecimalField")
  116. self.assertEqual(args, [])
  117. self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 0})
  118. def test_email_field(self):
  119. field = models.EmailField()
  120. name, path, args, kwargs = field.deconstruct()
  121. self.assertEqual(path, "django.db.models.EmailField")
  122. self.assertEqual(args, [])
  123. self.assertEqual(kwargs, {"max_length": 254})
  124. field = models.EmailField(max_length=255)
  125. name, path, args, kwargs = field.deconstruct()
  126. self.assertEqual(path, "django.db.models.EmailField")
  127. self.assertEqual(args, [])
  128. self.assertEqual(kwargs, {"max_length": 255})
  129. def test_file_field(self):
  130. field = models.FileField(upload_to="foo/bar")
  131. name, path, args, kwargs = field.deconstruct()
  132. self.assertEqual(path, "django.db.models.FileField")
  133. self.assertEqual(args, [])
  134. self.assertEqual(kwargs, {"upload_to": "foo/bar"})
  135. # Test max_length
  136. field = models.FileField(upload_to="foo/bar", max_length=200)
  137. name, path, args, kwargs = field.deconstruct()
  138. self.assertEqual(path, "django.db.models.FileField")
  139. self.assertEqual(args, [])
  140. self.assertEqual(kwargs, {"upload_to": "foo/bar", "max_length": 200})
  141. def test_file_path_field(self):
  142. field = models.FilePathField(match=".*\.txt$")
  143. name, path, args, kwargs = field.deconstruct()
  144. self.assertEqual(path, "django.db.models.FilePathField")
  145. self.assertEqual(args, [])
  146. self.assertEqual(kwargs, {"match": ".*\.txt$"})
  147. field = models.FilePathField(recursive=True, allow_folders=True, max_length=123)
  148. name, path, args, kwargs = field.deconstruct()
  149. self.assertEqual(path, "django.db.models.FilePathField")
  150. self.assertEqual(args, [])
  151. self.assertEqual(kwargs, {"recursive": True, "allow_folders": True, "max_length": 123})
  152. def test_float_field(self):
  153. field = models.FloatField()
  154. name, path, args, kwargs = field.deconstruct()
  155. self.assertEqual(path, "django.db.models.FloatField")
  156. self.assertEqual(args, [])
  157. self.assertEqual(kwargs, {})
  158. def test_foreign_key(self):
  159. # Test basic pointing
  160. from django.contrib.auth.models import Permission
  161. field = models.ForeignKey("auth.Permission", models.CASCADE)
  162. field.remote_field.model = Permission
  163. field.remote_field.field_name = "id"
  164. name, path, args, kwargs = field.deconstruct()
  165. self.assertEqual(path, "django.db.models.ForeignKey")
  166. self.assertEqual(args, [])
  167. self.assertEqual(kwargs, {"to": "auth.Permission", "on_delete": models.CASCADE})
  168. self.assertFalse(hasattr(kwargs['to'], "setting_name"))
  169. # Test swap detection for swappable model
  170. field = models.ForeignKey("auth.User", models.CASCADE)
  171. name, path, args, kwargs = field.deconstruct()
  172. self.assertEqual(path, "django.db.models.ForeignKey")
  173. self.assertEqual(args, [])
  174. self.assertEqual(kwargs, {"to": "auth.User", "on_delete": models.CASCADE})
  175. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  176. # Test nonexistent (for now) model
  177. field = models.ForeignKey("something.Else", models.CASCADE)
  178. name, path, args, kwargs = field.deconstruct()
  179. self.assertEqual(path, "django.db.models.ForeignKey")
  180. self.assertEqual(args, [])
  181. self.assertEqual(kwargs, {"to": "something.Else", "on_delete": models.CASCADE})
  182. # Test on_delete
  183. field = models.ForeignKey("auth.User", models.SET_NULL)
  184. name, path, args, kwargs = field.deconstruct()
  185. self.assertEqual(path, "django.db.models.ForeignKey")
  186. self.assertEqual(args, [])
  187. self.assertEqual(kwargs, {"to": "auth.User", "on_delete": models.SET_NULL})
  188. # Test to_field preservation
  189. field = models.ForeignKey("auth.Permission", models.CASCADE, to_field="foobar")
  190. name, path, args, kwargs = field.deconstruct()
  191. self.assertEqual(path, "django.db.models.ForeignKey")
  192. self.assertEqual(args, [])
  193. self.assertEqual(kwargs, {"to": "auth.Permission", "to_field": "foobar", "on_delete": models.CASCADE})
  194. # Test related_name preservation
  195. field = models.ForeignKey("auth.Permission", models.CASCADE, related_name="foobar")
  196. name, path, args, kwargs = field.deconstruct()
  197. self.assertEqual(path, "django.db.models.ForeignKey")
  198. self.assertEqual(args, [])
  199. self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "foobar", "on_delete": models.CASCADE})
  200. @override_settings(AUTH_USER_MODEL="auth.Permission")
  201. def test_foreign_key_swapped(self):
  202. # It doesn't matter that we swapped out user for permission;
  203. # there's no validation. We just want to check the setting stuff works.
  204. field = models.ForeignKey("auth.Permission", models.CASCADE)
  205. name, path, args, kwargs = field.deconstruct()
  206. self.assertEqual(path, "django.db.models.ForeignKey")
  207. self.assertEqual(args, [])
  208. self.assertEqual(kwargs, {"to": "auth.Permission", "on_delete": models.CASCADE})
  209. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  210. def test_image_field(self):
  211. field = models.ImageField(upload_to="foo/barness", width_field="width", height_field="height")
  212. name, path, args, kwargs = field.deconstruct()
  213. self.assertEqual(path, "django.db.models.ImageField")
  214. self.assertEqual(args, [])
  215. self.assertEqual(kwargs, {"upload_to": "foo/barness", "width_field": "width", "height_field": "height"})
  216. def test_integer_field(self):
  217. field = models.IntegerField()
  218. name, path, args, kwargs = field.deconstruct()
  219. self.assertEqual(path, "django.db.models.IntegerField")
  220. self.assertEqual(args, [])
  221. self.assertEqual(kwargs, {})
  222. def test_ip_address_field(self):
  223. field = models.IPAddressField()
  224. name, path, args, kwargs = field.deconstruct()
  225. self.assertEqual(path, "django.db.models.IPAddressField")
  226. self.assertEqual(args, [])
  227. self.assertEqual(kwargs, {})
  228. def test_generic_ip_address_field(self):
  229. field = models.GenericIPAddressField()
  230. name, path, args, kwargs = field.deconstruct()
  231. self.assertEqual(path, "django.db.models.GenericIPAddressField")
  232. self.assertEqual(args, [])
  233. self.assertEqual(kwargs, {})
  234. field = models.GenericIPAddressField(protocol="IPv6")
  235. name, path, args, kwargs = field.deconstruct()
  236. self.assertEqual(path, "django.db.models.GenericIPAddressField")
  237. self.assertEqual(args, [])
  238. self.assertEqual(kwargs, {"protocol": "IPv6"})
  239. def test_many_to_many_field(self):
  240. # Test normal
  241. field = models.ManyToManyField("auth.Permission")
  242. name, path, args, kwargs = field.deconstruct()
  243. self.assertEqual(path, "django.db.models.ManyToManyField")
  244. self.assertEqual(args, [])
  245. self.assertEqual(kwargs, {"to": "auth.Permission"})
  246. self.assertFalse(hasattr(kwargs['to'], "setting_name"))
  247. # Test swappable
  248. field = models.ManyToManyField("auth.User")
  249. name, path, args, kwargs = field.deconstruct()
  250. self.assertEqual(path, "django.db.models.ManyToManyField")
  251. self.assertEqual(args, [])
  252. self.assertEqual(kwargs, {"to": "auth.User"})
  253. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  254. # Test through
  255. field = models.ManyToManyField("auth.Permission", through="auth.Group")
  256. name, path, args, kwargs = field.deconstruct()
  257. self.assertEqual(path, "django.db.models.ManyToManyField")
  258. self.assertEqual(args, [])
  259. self.assertEqual(kwargs, {"to": "auth.Permission", "through": "auth.Group"})
  260. # Test custom db_table
  261. field = models.ManyToManyField("auth.Permission", db_table="custom_table")
  262. name, path, args, kwargs = field.deconstruct()
  263. self.assertEqual(path, "django.db.models.ManyToManyField")
  264. self.assertEqual(args, [])
  265. self.assertEqual(kwargs, {"to": "auth.Permission", "db_table": "custom_table"})
  266. # Test related_name
  267. field = models.ManyToManyField("auth.Permission", related_name="custom_table")
  268. name, path, args, kwargs = field.deconstruct()
  269. self.assertEqual(path, "django.db.models.ManyToManyField")
  270. self.assertEqual(args, [])
  271. self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "custom_table"})
  272. @override_settings(AUTH_USER_MODEL="auth.Permission")
  273. def test_many_to_many_field_swapped(self):
  274. # It doesn't matter that we swapped out user for permission;
  275. # there's no validation. We just want to check the setting stuff works.
  276. field = models.ManyToManyField("auth.Permission")
  277. name, path, args, kwargs = field.deconstruct()
  278. self.assertEqual(path, "django.db.models.ManyToManyField")
  279. self.assertEqual(args, [])
  280. self.assertEqual(kwargs, {"to": "auth.Permission"})
  281. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  282. def test_null_boolean_field(self):
  283. field = models.NullBooleanField()
  284. name, path, args, kwargs = field.deconstruct()
  285. self.assertEqual(path, "django.db.models.NullBooleanField")
  286. self.assertEqual(args, [])
  287. self.assertEqual(kwargs, {})
  288. def test_positive_integer_field(self):
  289. field = models.PositiveIntegerField()
  290. name, path, args, kwargs = field.deconstruct()
  291. self.assertEqual(path, "django.db.models.PositiveIntegerField")
  292. self.assertEqual(args, [])
  293. self.assertEqual(kwargs, {})
  294. def test_positive_small_integer_field(self):
  295. field = models.PositiveSmallIntegerField()
  296. name, path, args, kwargs = field.deconstruct()
  297. self.assertEqual(path, "django.db.models.PositiveSmallIntegerField")
  298. self.assertEqual(args, [])
  299. self.assertEqual(kwargs, {})
  300. def test_slug_field(self):
  301. field = models.SlugField()
  302. name, path, args, kwargs = field.deconstruct()
  303. self.assertEqual(path, "django.db.models.SlugField")
  304. self.assertEqual(args, [])
  305. self.assertEqual(kwargs, {})
  306. field = models.SlugField(db_index=False, max_length=231)
  307. name, path, args, kwargs = field.deconstruct()
  308. self.assertEqual(path, "django.db.models.SlugField")
  309. self.assertEqual(args, [])
  310. self.assertEqual(kwargs, {"db_index": False, "max_length": 231})
  311. def test_small_integer_field(self):
  312. field = models.SmallIntegerField()
  313. name, path, args, kwargs = field.deconstruct()
  314. self.assertEqual(path, "django.db.models.SmallIntegerField")
  315. self.assertEqual(args, [])
  316. self.assertEqual(kwargs, {})
  317. def test_text_field(self):
  318. field = models.TextField()
  319. name, path, args, kwargs = field.deconstruct()
  320. self.assertEqual(path, "django.db.models.TextField")
  321. self.assertEqual(args, [])
  322. self.assertEqual(kwargs, {})
  323. def test_time_field(self):
  324. field = models.TimeField()
  325. name, path, args, kwargs = field.deconstruct()
  326. self.assertEqual(path, "django.db.models.TimeField")
  327. self.assertEqual(args, [])
  328. self.assertEqual(kwargs, {})
  329. field = models.TimeField(auto_now=True)
  330. name, path, args, kwargs = field.deconstruct()
  331. self.assertEqual(args, [])
  332. self.assertEqual(kwargs, {'auto_now': True})
  333. field = models.TimeField(auto_now_add=True)
  334. name, path, args, kwargs = field.deconstruct()
  335. self.assertEqual(args, [])
  336. self.assertEqual(kwargs, {'auto_now_add': True})
  337. def test_url_field(self):
  338. field = models.URLField()
  339. name, path, args, kwargs = field.deconstruct()
  340. self.assertEqual(path, "django.db.models.URLField")
  341. self.assertEqual(args, [])
  342. self.assertEqual(kwargs, {})
  343. field = models.URLField(max_length=231)
  344. name, path, args, kwargs = field.deconstruct()
  345. self.assertEqual(path, "django.db.models.URLField")
  346. self.assertEqual(args, [])
  347. self.assertEqual(kwargs, {"max_length": 231})
  348. def test_binary_field(self):
  349. field = models.BinaryField()
  350. name, path, args, kwargs = field.deconstruct()
  351. self.assertEqual(path, "django.db.models.BinaryField")
  352. self.assertEqual(args, [])
  353. self.assertEqual(kwargs, {})