tests.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import warnings
  2. from django.db import models
  3. from django.test import TestCase, override_settings
  4. from django.utils import six
  5. class FieldDeconstructionTests(TestCase):
  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")
  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_csi_field(self):
  64. field = models.CommaSeparatedIntegerField(max_length=100)
  65. name, path, args, kwargs = field.deconstruct()
  66. self.assertEqual(path, "django.db.models.CommaSeparatedIntegerField")
  67. self.assertEqual(args, [])
  68. self.assertEqual(kwargs, {"max_length": 100})
  69. def test_date_field(self):
  70. field = models.DateField()
  71. name, path, args, kwargs = field.deconstruct()
  72. self.assertEqual(path, "django.db.models.DateField")
  73. self.assertEqual(args, [])
  74. self.assertEqual(kwargs, {})
  75. field = models.DateField(auto_now=True)
  76. name, path, args, kwargs = field.deconstruct()
  77. self.assertEqual(path, "django.db.models.DateField")
  78. self.assertEqual(args, [])
  79. self.assertEqual(kwargs, {"auto_now": True})
  80. def test_datetime_field(self):
  81. field = models.DateTimeField()
  82. name, path, args, kwargs = field.deconstruct()
  83. self.assertEqual(path, "django.db.models.DateTimeField")
  84. self.assertEqual(args, [])
  85. self.assertEqual(kwargs, {})
  86. field = models.DateTimeField(auto_now_add=True)
  87. name, path, args, kwargs = field.deconstruct()
  88. self.assertEqual(path, "django.db.models.DateTimeField")
  89. self.assertEqual(args, [])
  90. self.assertEqual(kwargs, {"auto_now_add": True})
  91. # Bug #21785
  92. field = models.DateTimeField(auto_now=True, 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, "auto_now": True})
  97. def test_decimal_field(self):
  98. field = models.DecimalField(max_digits=5, decimal_places=2)
  99. name, path, args, kwargs = field.deconstruct()
  100. self.assertEqual(path, "django.db.models.DecimalField")
  101. self.assertEqual(args, [])
  102. self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 2})
  103. def test_decimal_field_0_decimal_places(self):
  104. """
  105. A DecimalField with decimal_places=0 should work (#22272).
  106. """
  107. field = models.DecimalField(max_digits=5, decimal_places=0)
  108. name, path, args, kwargs = field.deconstruct()
  109. self.assertEqual(path, "django.db.models.DecimalField")
  110. self.assertEqual(args, [])
  111. self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 0})
  112. def test_email_field(self):
  113. field = models.EmailField()
  114. name, path, args, kwargs = field.deconstruct()
  115. self.assertEqual(path, "django.db.models.EmailField")
  116. self.assertEqual(args, [])
  117. self.assertEqual(kwargs, {"max_length": 254})
  118. field = models.EmailField(max_length=255)
  119. name, path, args, kwargs = field.deconstruct()
  120. self.assertEqual(path, "django.db.models.EmailField")
  121. self.assertEqual(args, [])
  122. self.assertEqual(kwargs, {"max_length": 255})
  123. def test_file_field(self):
  124. field = models.FileField(upload_to="foo/bar")
  125. name, path, args, kwargs = field.deconstruct()
  126. self.assertEqual(path, "django.db.models.FileField")
  127. self.assertEqual(args, [])
  128. self.assertEqual(kwargs, {"upload_to": "foo/bar"})
  129. # Test max_length
  130. field = models.FileField(upload_to="foo/bar", max_length=200)
  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", "max_length": 200})
  135. def test_file_path_field(self):
  136. field = models.FilePathField(match=".*\.txt$")
  137. name, path, args, kwargs = field.deconstruct()
  138. self.assertEqual(path, "django.db.models.FilePathField")
  139. self.assertEqual(args, [])
  140. self.assertEqual(kwargs, {"match": ".*\.txt$"})
  141. field = models.FilePathField(recursive=True, allow_folders=True, max_length=123)
  142. name, path, args, kwargs = field.deconstruct()
  143. self.assertEqual(path, "django.db.models.FilePathField")
  144. self.assertEqual(args, [])
  145. self.assertEqual(kwargs, {"recursive": True, "allow_folders": True, "max_length": 123})
  146. def test_float_field(self):
  147. field = models.FloatField()
  148. name, path, args, kwargs = field.deconstruct()
  149. self.assertEqual(path, "django.db.models.FloatField")
  150. self.assertEqual(args, [])
  151. self.assertEqual(kwargs, {})
  152. def test_foreign_key(self):
  153. # Test basic pointing
  154. from django.contrib.auth.models import Permission
  155. field = models.ForeignKey("auth.Permission")
  156. field.rel.to = Permission
  157. field.rel.field_name = "id"
  158. name, path, args, kwargs = field.deconstruct()
  159. self.assertEqual(path, "django.db.models.ForeignKey")
  160. self.assertEqual(args, [])
  161. self.assertEqual(kwargs, {"to": "auth.Permission"})
  162. self.assertFalse(hasattr(kwargs['to'], "setting_name"))
  163. # Test swap detection for swappable model
  164. field = models.ForeignKey("auth.User")
  165. name, path, args, kwargs = field.deconstruct()
  166. self.assertEqual(path, "django.db.models.ForeignKey")
  167. self.assertEqual(args, [])
  168. self.assertEqual(kwargs, {"to": "auth.User"})
  169. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  170. # Test nonexistent (for now) model
  171. field = models.ForeignKey("something.Else")
  172. name, path, args, kwargs = field.deconstruct()
  173. self.assertEqual(path, "django.db.models.ForeignKey")
  174. self.assertEqual(args, [])
  175. self.assertEqual(kwargs, {"to": "something.Else"})
  176. # Test on_delete
  177. field = models.ForeignKey("auth.User", on_delete=models.SET_NULL)
  178. name, path, args, kwargs = field.deconstruct()
  179. self.assertEqual(path, "django.db.models.ForeignKey")
  180. self.assertEqual(args, [])
  181. self.assertEqual(kwargs, {"to": "auth.User", "on_delete": models.SET_NULL})
  182. # Test to_field preservation
  183. field = models.ForeignKey("auth.Permission", to_field="foobar")
  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.Permission", "to_field": "foobar"})
  188. @override_settings(AUTH_USER_MODEL="auth.Permission")
  189. def test_foreign_key_swapped(self):
  190. # It doesn't matter that we swapped out user for permission;
  191. # there's no validation. We just want to check the setting stuff works.
  192. field = models.ForeignKey("auth.Permission")
  193. name, path, args, kwargs = field.deconstruct()
  194. self.assertEqual(path, "django.db.models.ForeignKey")
  195. self.assertEqual(args, [])
  196. self.assertEqual(kwargs, {"to": "auth.Permission"})
  197. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  198. def test_image_field(self):
  199. field = models.ImageField(upload_to="foo/barness", width_field="width", height_field="height")
  200. name, path, args, kwargs = field.deconstruct()
  201. self.assertEqual(path, "django.db.models.ImageField")
  202. self.assertEqual(args, [])
  203. self.assertEqual(kwargs, {"upload_to": "foo/barness", "width_field": "width", "height_field": "height"})
  204. def test_integer_field(self):
  205. field = models.IntegerField()
  206. name, path, args, kwargs = field.deconstruct()
  207. self.assertEqual(path, "django.db.models.IntegerField")
  208. self.assertEqual(args, [])
  209. self.assertEqual(kwargs, {})
  210. def test_ip_address_field(self):
  211. with warnings.catch_warnings(record=True):
  212. warnings.simplefilter("always")
  213. field = models.IPAddressField()
  214. name, path, args, kwargs = field.deconstruct()
  215. self.assertEqual(path, "django.db.models.IPAddressField")
  216. self.assertEqual(args, [])
  217. self.assertEqual(kwargs, {})
  218. def test_generic_ip_address_field(self):
  219. field = models.GenericIPAddressField()
  220. name, path, args, kwargs = field.deconstruct()
  221. self.assertEqual(path, "django.db.models.GenericIPAddressField")
  222. self.assertEqual(args, [])
  223. self.assertEqual(kwargs, {})
  224. field = models.GenericIPAddressField(protocol="IPv6")
  225. name, path, args, kwargs = field.deconstruct()
  226. self.assertEqual(path, "django.db.models.GenericIPAddressField")
  227. self.assertEqual(args, [])
  228. self.assertEqual(kwargs, {"protocol": "IPv6"})
  229. def test_many_to_many_field(self):
  230. # Test normal
  231. field = models.ManyToManyField("auth.Permission")
  232. name, path, args, kwargs = field.deconstruct()
  233. self.assertEqual(path, "django.db.models.ManyToManyField")
  234. self.assertEqual(args, [])
  235. self.assertEqual(kwargs, {"to": "auth.Permission"})
  236. self.assertFalse(hasattr(kwargs['to'], "setting_name"))
  237. # Test swappable
  238. field = models.ManyToManyField("auth.User")
  239. name, path, args, kwargs = field.deconstruct()
  240. self.assertEqual(path, "django.db.models.ManyToManyField")
  241. self.assertEqual(args, [])
  242. self.assertEqual(kwargs, {"to": "auth.User"})
  243. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  244. # Test through
  245. field = models.ManyToManyField("auth.Permission", through="auth.Group")
  246. name, path, args, kwargs = field.deconstruct()
  247. self.assertEqual(path, "django.db.models.ManyToManyField")
  248. self.assertEqual(args, [])
  249. self.assertEqual(kwargs, {"to": "auth.Permission", "through": "auth.Group"})
  250. # Test custom db_table
  251. field = models.ManyToManyField("auth.Permission", db_table="custom_table")
  252. name, path, args, kwargs = field.deconstruct()
  253. self.assertEqual(path, "django.db.models.ManyToManyField")
  254. self.assertEqual(args, [])
  255. self.assertEqual(kwargs, {"to": "auth.Permission", "db_table": "custom_table"})
  256. @override_settings(AUTH_USER_MODEL="auth.Permission")
  257. def test_many_to_many_field_swapped(self):
  258. # It doesn't matter that we swapped out user for permission;
  259. # there's no validation. We just want to check the setting stuff works.
  260. field = models.ManyToManyField("auth.Permission")
  261. name, path, args, kwargs = field.deconstruct()
  262. self.assertEqual(path, "django.db.models.ManyToManyField")
  263. self.assertEqual(args, [])
  264. self.assertEqual(kwargs, {"to": "auth.Permission"})
  265. self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
  266. def test_null_boolean_field(self):
  267. field = models.NullBooleanField()
  268. name, path, args, kwargs = field.deconstruct()
  269. self.assertEqual(path, "django.db.models.NullBooleanField")
  270. self.assertEqual(args, [])
  271. self.assertEqual(kwargs, {})
  272. def test_positive_integer_field(self):
  273. field = models.PositiveIntegerField()
  274. name, path, args, kwargs = field.deconstruct()
  275. self.assertEqual(path, "django.db.models.PositiveIntegerField")
  276. self.assertEqual(args, [])
  277. self.assertEqual(kwargs, {})
  278. def test_positive_small_integer_field(self):
  279. field = models.PositiveSmallIntegerField()
  280. name, path, args, kwargs = field.deconstruct()
  281. self.assertEqual(path, "django.db.models.PositiveSmallIntegerField")
  282. self.assertEqual(args, [])
  283. self.assertEqual(kwargs, {})
  284. def test_slug_field(self):
  285. field = models.SlugField()
  286. name, path, args, kwargs = field.deconstruct()
  287. self.assertEqual(path, "django.db.models.SlugField")
  288. self.assertEqual(args, [])
  289. self.assertEqual(kwargs, {})
  290. field = models.SlugField(db_index=False, max_length=231)
  291. name, path, args, kwargs = field.deconstruct()
  292. self.assertEqual(path, "django.db.models.SlugField")
  293. self.assertEqual(args, [])
  294. self.assertEqual(kwargs, {"db_index": False, "max_length": 231})
  295. def test_small_integer_field(self):
  296. field = models.SmallIntegerField()
  297. name, path, args, kwargs = field.deconstruct()
  298. self.assertEqual(path, "django.db.models.SmallIntegerField")
  299. self.assertEqual(args, [])
  300. self.assertEqual(kwargs, {})
  301. def test_text_field(self):
  302. field = models.TextField()
  303. name, path, args, kwargs = field.deconstruct()
  304. self.assertEqual(path, "django.db.models.TextField")
  305. self.assertEqual(args, [])
  306. self.assertEqual(kwargs, {})
  307. def test_url_field(self):
  308. field = models.URLField()
  309. name, path, args, kwargs = field.deconstruct()
  310. self.assertEqual(path, "django.db.models.URLField")
  311. self.assertEqual(args, [])
  312. self.assertEqual(kwargs, {})
  313. field = models.URLField(max_length=231)
  314. name, path, args, kwargs = field.deconstruct()
  315. self.assertEqual(path, "django.db.models.URLField")
  316. self.assertEqual(args, [])
  317. self.assertEqual(kwargs, {"max_length": 231})