test_ordinary_fields.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. # -*- encoding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import unittest
  4. from django.core.checks import Error
  5. from django.db import connection, models
  6. from .base import IsolatedModelsTestCase
  7. class AutoFieldTests(IsolatedModelsTestCase):
  8. def test_valid_case(self):
  9. class Model(models.Model):
  10. id = models.AutoField(primary_key=True)
  11. field = Model._meta.get_field('id')
  12. errors = field.check()
  13. expected = []
  14. self.assertEqual(errors, expected)
  15. def test_primary_key(self):
  16. # primary_key must be True. Refs #12467.
  17. class Model(models.Model):
  18. field = models.AutoField(primary_key=False)
  19. # Prevent Django from autocreating `id` AutoField, which would
  20. # result in an error, because a model must have exactly one
  21. # AutoField.
  22. another = models.IntegerField(primary_key=True)
  23. field = Model._meta.get_field('field')
  24. errors = field.check()
  25. expected = [
  26. Error(
  27. 'AutoFields must set primary_key=True.',
  28. hint=None,
  29. obj=field,
  30. id='fields.E100',
  31. ),
  32. ]
  33. self.assertEqual(errors, expected)
  34. class BooleanFieldTests(IsolatedModelsTestCase):
  35. def test_nullable_boolean_field(self):
  36. class Model(models.Model):
  37. field = models.BooleanField(null=True)
  38. field = Model._meta.get_field('field')
  39. errors = field.check()
  40. expected = [
  41. Error(
  42. 'BooleanFields do not accept null values.',
  43. hint='Use a NullBooleanField instead.',
  44. obj=field,
  45. id='fields.E110',
  46. ),
  47. ]
  48. self.assertEqual(errors, expected)
  49. class CharFieldTests(IsolatedModelsTestCase):
  50. def test_valid_field(self):
  51. class Model(models.Model):
  52. field = models.CharField(
  53. max_length=255,
  54. choices=[
  55. ('1', 'item1'),
  56. ('2', 'item2'),
  57. ],
  58. db_index=True)
  59. field = Model._meta.get_field('field')
  60. errors = field.check()
  61. expected = []
  62. self.assertEqual(errors, expected)
  63. def test_missing_max_length(self):
  64. class Model(models.Model):
  65. field = models.CharField()
  66. field = Model._meta.get_field('field')
  67. errors = field.check()
  68. expected = [
  69. Error(
  70. "CharFields must define a 'max_length' attribute.",
  71. hint=None,
  72. obj=field,
  73. id='fields.E120',
  74. ),
  75. ]
  76. self.assertEqual(errors, expected)
  77. def test_negative_max_length(self):
  78. class Model(models.Model):
  79. field = models.CharField(max_length=-1)
  80. field = Model._meta.get_field('field')
  81. errors = field.check()
  82. expected = [
  83. Error(
  84. "'max_length' must be a positive integer.",
  85. hint=None,
  86. obj=field,
  87. id='fields.E121',
  88. ),
  89. ]
  90. self.assertEqual(errors, expected)
  91. def test_bad_max_length_value(self):
  92. class Model(models.Model):
  93. field = models.CharField(max_length="bad")
  94. field = Model._meta.get_field('field')
  95. errors = field.check()
  96. expected = [
  97. Error(
  98. "'max_length' must be a positive integer.",
  99. hint=None,
  100. obj=field,
  101. id='fields.E121',
  102. ),
  103. ]
  104. self.assertEqual(errors, expected)
  105. def test_non_iterable_choices(self):
  106. class Model(models.Model):
  107. field = models.CharField(max_length=10, choices='bad')
  108. field = Model._meta.get_field('field')
  109. errors = field.check()
  110. expected = [
  111. Error(
  112. "'choices' must be an iterable (e.g., a list or tuple).",
  113. hint=None,
  114. obj=field,
  115. id='fields.E004',
  116. ),
  117. ]
  118. self.assertEqual(errors, expected)
  119. def test_choices_containing_non_pairs(self):
  120. class Model(models.Model):
  121. field = models.CharField(max_length=10, choices=[(1, 2, 3), (1, 2, 3)])
  122. field = Model._meta.get_field('field')
  123. errors = field.check()
  124. expected = [
  125. Error(
  126. "'choices' must be an iterable containing (actual value, human readable name) tuples.",
  127. hint=None,
  128. obj=field,
  129. id='fields.E005',
  130. ),
  131. ]
  132. self.assertEqual(errors, expected)
  133. def test_bad_db_index_value(self):
  134. class Model(models.Model):
  135. field = models.CharField(max_length=10, db_index='bad')
  136. field = Model._meta.get_field('field')
  137. errors = field.check()
  138. expected = [
  139. Error(
  140. "'db_index' must be None, True or False.",
  141. hint=None,
  142. obj=field,
  143. id='fields.E006',
  144. ),
  145. ]
  146. self.assertEqual(errors, expected)
  147. @unittest.skipUnless(connection.vendor == 'mysql',
  148. "Test valid only for MySQL")
  149. def test_too_long_char_field_under_mysql(self):
  150. from django.db.backends.mysql.validation import DatabaseValidation
  151. class Model(models.Model):
  152. field = models.CharField(unique=True, max_length=256)
  153. field = Model._meta.get_field('field')
  154. validator = DatabaseValidation(connection=None)
  155. errors = validator.check_field(field)
  156. expected = [
  157. Error(
  158. 'MySQL does not allow unique CharFields to have a max_length > 255.',
  159. hint=None,
  160. obj=field,
  161. id='mysql.E001',
  162. )
  163. ]
  164. self.assertEqual(errors, expected)
  165. class DecimalFieldTests(IsolatedModelsTestCase):
  166. def test_required_attributes(self):
  167. class Model(models.Model):
  168. field = models.DecimalField()
  169. field = Model._meta.get_field('field')
  170. errors = field.check()
  171. expected = [
  172. Error(
  173. "DecimalFields must define a 'decimal_places' attribute.",
  174. hint=None,
  175. obj=field,
  176. id='fields.E130',
  177. ),
  178. Error(
  179. "DecimalFields must define a 'max_digits' attribute.",
  180. hint=None,
  181. obj=field,
  182. id='fields.E132',
  183. ),
  184. ]
  185. self.assertEqual(errors, expected)
  186. def test_negative_max_digits_and_decimal_places(self):
  187. class Model(models.Model):
  188. field = models.DecimalField(max_digits=-1, decimal_places=-1)
  189. field = Model._meta.get_field('field')
  190. errors = field.check()
  191. expected = [
  192. Error(
  193. "'decimal_places' must be a non-negative integer.",
  194. hint=None,
  195. obj=field,
  196. id='fields.E131',
  197. ),
  198. Error(
  199. "'max_digits' must be a positive integer.",
  200. hint=None,
  201. obj=field,
  202. id='fields.E133',
  203. ),
  204. ]
  205. self.assertEqual(errors, expected)
  206. def test_bad_values_of_max_digits_and_decimal_places(self):
  207. class Model(models.Model):
  208. field = models.DecimalField(max_digits="bad", decimal_places="bad")
  209. field = Model._meta.get_field('field')
  210. errors = field.check()
  211. expected = [
  212. Error(
  213. "'decimal_places' must be a non-negative integer.",
  214. hint=None,
  215. obj=field,
  216. id='fields.E131',
  217. ),
  218. Error(
  219. "'max_digits' must be a positive integer.",
  220. hint=None,
  221. obj=field,
  222. id='fields.E133',
  223. ),
  224. ]
  225. self.assertEqual(errors, expected)
  226. def test_decimal_places_greater_than_max_digits(self):
  227. class Model(models.Model):
  228. field = models.DecimalField(max_digits=9, decimal_places=10)
  229. field = Model._meta.get_field('field')
  230. errors = field.check()
  231. expected = [
  232. Error(
  233. "'max_digits' must be greater or equal to 'decimal_places'.",
  234. hint=None,
  235. obj=field,
  236. id='fields.E134',
  237. ),
  238. ]
  239. self.assertEqual(errors, expected)
  240. def test_valid_field(self):
  241. class Model(models.Model):
  242. field = models.DecimalField(max_digits=10, decimal_places=10)
  243. field = Model._meta.get_field('field')
  244. errors = field.check()
  245. expected = []
  246. self.assertEqual(errors, expected)
  247. class FileFieldTests(IsolatedModelsTestCase):
  248. def test_valid_case(self):
  249. class Model(models.Model):
  250. field = models.FileField(upload_to='somewhere')
  251. field = Model._meta.get_field('field')
  252. errors = field.check()
  253. expected = []
  254. self.assertEqual(errors, expected)
  255. def test_unique(self):
  256. class Model(models.Model):
  257. field = models.FileField(unique=False, upload_to='somewhere')
  258. field = Model._meta.get_field('field')
  259. errors = field.check()
  260. expected = [
  261. Error(
  262. "'unique' is not a valid argument for a FileField.",
  263. hint=None,
  264. obj=field,
  265. id='fields.E200',
  266. )
  267. ]
  268. self.assertEqual(errors, expected)
  269. def test_primary_key(self):
  270. class Model(models.Model):
  271. field = models.FileField(primary_key=False, upload_to='somewhere')
  272. field = Model._meta.get_field('field')
  273. errors = field.check()
  274. expected = [
  275. Error(
  276. "'primary_key' is not a valid argument for a FileField.",
  277. hint=None,
  278. obj=field,
  279. id='fields.E201',
  280. )
  281. ]
  282. self.assertEqual(errors, expected)
  283. class FilePathFieldTests(IsolatedModelsTestCase):
  284. def test_forbidden_files_and_folders(self):
  285. class Model(models.Model):
  286. field = models.FilePathField(allow_files=False, allow_folders=False)
  287. field = Model._meta.get_field('field')
  288. errors = field.check()
  289. expected = [
  290. Error(
  291. "FilePathFields must have either 'allow_files' or 'allow_folders' set to True.",
  292. hint=None,
  293. obj=field,
  294. id='fields.E140',
  295. ),
  296. ]
  297. self.assertEqual(errors, expected)
  298. class GenericIPAddressFieldTests(IsolatedModelsTestCase):
  299. def test_non_nullable_blank(self):
  300. class Model(models.Model):
  301. field = models.GenericIPAddressField(null=False, blank=True)
  302. field = Model._meta.get_field('field')
  303. errors = field.check()
  304. expected = [
  305. Error(
  306. ('GenericIPAddressFields cannot have blank=True if null=False, '
  307. 'as blank values are stored as nulls.'),
  308. hint=None,
  309. obj=field,
  310. id='fields.E150',
  311. ),
  312. ]
  313. self.assertEqual(errors, expected)
  314. class ImageFieldTests(IsolatedModelsTestCase):
  315. def test_pillow_installed(self):
  316. try:
  317. from PIL import Image # NOQA
  318. except ImportError:
  319. pillow_installed = False
  320. else:
  321. pillow_installed = True
  322. class Model(models.Model):
  323. field = models.ImageField(upload_to='somewhere')
  324. field = Model._meta.get_field('field')
  325. errors = field.check()
  326. expected = [] if pillow_installed else [
  327. Error(
  328. 'Cannot use ImageField because Pillow is not installed.',
  329. hint=('Get Pillow at https://pypi.python.org/pypi/Pillow '
  330. 'or run command "pip install pillow".'),
  331. obj=field,
  332. id='fields.E210',
  333. ),
  334. ]
  335. self.assertEqual(errors, expected)