1 from __future__
import absolute_import
, unicode_literals
4 from decimal
import Decimal
6 from django
import test
7 from django
import forms
8 from django
.core
.exceptions
import ValidationError
9 from django
.db
.models
.fields
import (
10 AutoField
, BigIntegerField
, BooleanField
, CharField
,
11 CommaSeparatedIntegerField
, DateField
, DateTimeField
, DecimalField
,
12 EmailField
, FilePathField
, FloatField
, IntegerField
, IPAddressField
,
13 GenericIPAddressField
, NullBooleanField
, PositiveIntegerField
,
14 PositiveSmallIntegerField
, SlugField
, SmallIntegerField
, TextField
,
16 from django
.db
import models
17 from django
.db
.models
.fields
.files
import FileField
, ImageField
, FieldFile
18 from django
.utils
import six
19 from django
.utils
import unittest
21 from .models
import (Foo
, Bar
, Whiz
, BigD
, BigS
, Image
, BigInt
, Post
,
22 NullBooleanModel
, BooleanModel
, Document
, RenamedField
, VerboseNameField
,
25 from .imagefield
import (ImageFieldTests
, ImageFieldTwoDimensionsTests
,
26 TwoImageFieldTests
, ImageFieldNoDimensionsTests
,
27 ImageFieldOneDimensionTests
, ImageFieldDimensionsFirstTests
,
28 ImageFieldUsingFileTests
)
31 class BasicFieldTests(test
.TestCase
):
32 def test_show_hidden_initial(self
):
34 Regression test for #12913. Make sure fields with choices respect
35 show_hidden_initial as a kwarg to models.Field.formfield()
37 choices
= [(0, 0), (1, 1)]
38 model_field
= models
.Field(choices
=choices
)
39 form_field
= model_field
.formfield(show_hidden_initial
=True)
40 self
.assertTrue(form_field
.show_hidden_initial
)
42 form_field
= model_field
.formfield(show_hidden_initial
=False)
43 self
.assertFalse(form_field
.show_hidden_initial
)
45 def test_nullbooleanfield_blank(self
):
47 Regression test for #13071: NullBooleanField should not throw
48 a validation error when given a value of None.
51 nullboolean
= NullBooleanModel(nbfield
=None)
53 nullboolean
.full_clean()
54 except ValidationError
as e
:
55 self
.fail("NullBooleanField failed validation with value of None: %s" % e
.messages
)
57 def test_field_repr(self
):
59 Regression test for #5931: __repr__ of a field also displays its name
61 f
= Foo
._meta
.get_field('a')
62 self
.assertEqual(repr(f
), '<django.db.models.fields.CharField: a>')
63 f
= models
.fields
.CharField()
64 self
.assertEqual(repr(f
), '<django.db.models.fields.CharField>')
66 def test_field_name(self
):
68 Regression test for #14695: explicitly defined field name overwritten
69 by model's attribute name.
71 instance
= RenamedField()
72 self
.assertTrue(hasattr(instance
, 'get_fieldname_display'))
73 self
.assertFalse(hasattr(instance
, 'get_modelname_display'))
75 def test_field_verbose_name(self
):
77 for i
in range(1, 23):
78 self
.assertEqual(m
._meta
.get_field('field%d' % i
).verbose_name
,
79 'verbose field%d' % i
)
81 self
.assertEqual(m
._meta
.get_field('id').verbose_name
, 'verbose pk')
83 class DecimalFieldTests(test
.TestCase
):
84 def test_to_python(self
):
85 f
= models
.DecimalField(max_digits
=4, decimal_places
=2)
86 self
.assertEqual(f
.to_python(3), Decimal("3"))
87 self
.assertEqual(f
.to_python("3.14"), Decimal("3.14"))
88 self
.assertRaises(ValidationError
, f
.to_python
, "abc")
90 def test_default(self
):
91 f
= models
.DecimalField(default
=Decimal("0.00"))
92 self
.assertEqual(f
.get_default(), Decimal("0.00"))
94 def test_format(self
):
95 f
= models
.DecimalField(max_digits
=5, decimal_places
=1)
96 self
.assertEqual(f
._format
(f
.to_python(2)), '2.0')
97 self
.assertEqual(f
._format
(f
.to_python('2.6')), '2.6')
98 self
.assertEqual(f
._format
(None), None)
100 def test_get_db_prep_lookup(self
):
101 from django
.db
import connection
102 f
= models
.DecimalField(max_digits
=5, decimal_places
=1)
103 self
.assertEqual(f
.get_db_prep_lookup('exact', None, connection
=connection
), [None])
105 def test_filter_with_strings(self
):
107 We should be able to filter decimal fields using strings (#8023)
109 Foo
.objects
.create(id=1, a
='abc', d
=Decimal("12.34"))
110 self
.assertEqual(list(Foo
.objects
.filter(d
='1.23')), [])
112 def test_save_without_float_conversion(self
):
114 Ensure decimals don't go through a corrupting float conversion during
119 bd
= BigD
.objects
.get(pk
=bd
.pk
)
120 self
.assertEqual(bd
.d
, Decimal("12.9"))
122 def test_lookup_really_big_value(self
):
124 Ensure that really big values can be used in a filter statement, even
125 with older Python versions.
127 # This should not crash. That counts as a win for our purposes.
128 Foo
.objects
.filter(d__gte
=100000000000)
130 class ForeignKeyTests(test
.TestCase
):
131 def test_callable_default(self
):
132 """Test the use of a lazy callable for ForeignKey.default"""
133 a
= Foo
.objects
.create(id=1, a
='abc', d
=Decimal("12.34"))
134 b
= Bar
.objects
.create(b
="bcd")
135 self
.assertEqual(b
.a
, a
)
137 class DateTimeFieldTests(unittest
.TestCase
):
138 def test_datetimefield_to_python_usecs(self
):
139 """DateTimeField.to_python should support usecs"""
140 f
= models
.DateTimeField()
141 self
.assertEqual(f
.to_python('2001-01-02 03:04:05.000006'),
142 datetime
.datetime(2001, 1, 2, 3, 4, 5, 6))
143 self
.assertEqual(f
.to_python('2001-01-02 03:04:05.999999'),
144 datetime
.datetime(2001, 1, 2, 3, 4, 5, 999999))
146 def test_timefield_to_python_usecs(self
):
147 """TimeField.to_python should support usecs"""
148 f
= models
.TimeField()
149 self
.assertEqual(f
.to_python('01:02:03.000004'),
150 datetime
.time(1, 2, 3, 4))
151 self
.assertEqual(f
.to_python('01:02:03.999999'),
152 datetime
.time(1, 2, 3, 999999))
154 class BooleanFieldTests(unittest
.TestCase
):
155 def _test_get_db_prep_lookup(self
, f
):
156 from django
.db
import connection
157 self
.assertEqual(f
.get_db_prep_lookup('exact', True, connection
=connection
), [True])
158 self
.assertEqual(f
.get_db_prep_lookup('exact', '1', connection
=connection
), [True])
159 self
.assertEqual(f
.get_db_prep_lookup('exact', 1, connection
=connection
), [True])
160 self
.assertEqual(f
.get_db_prep_lookup('exact', False, connection
=connection
), [False])
161 self
.assertEqual(f
.get_db_prep_lookup('exact', '0', connection
=connection
), [False])
162 self
.assertEqual(f
.get_db_prep_lookup('exact', 0, connection
=connection
), [False])
163 self
.assertEqual(f
.get_db_prep_lookup('exact', None, connection
=connection
), [None])
165 def _test_to_python(self
, f
):
166 self
.assertTrue(f
.to_python(1) is True)
167 self
.assertTrue(f
.to_python(0) is False)
169 def test_booleanfield_get_db_prep_lookup(self
):
170 self
._test
_get
_db
_prep
_lookup
(models
.BooleanField())
172 def test_nullbooleanfield_get_db_prep_lookup(self
):
173 self
._test
_get
_db
_prep
_lookup
(models
.NullBooleanField())
175 def test_booleanfield_to_python(self
):
176 self
._test
_to
_python
(models
.BooleanField())
178 def test_nullbooleanfield_to_python(self
):
179 self
._test
_to
_python
(models
.NullBooleanField())
181 def test_booleanfield_choices_blank(self
):
183 Test that BooleanField with choices and defaults doesn't generate a
184 formfield with the blank option (#9640, #10549).
186 choices
= [(1, 'Si'), (2, 'No')]
187 f
= models
.BooleanField(choices
=choices
, default
=1, null
=True)
188 self
.assertEqual(f
.formfield().choices
, [('', '---------')] + choices
)
190 f
= models
.BooleanField(choices
=choices
, default
=1, null
=False)
191 self
.assertEqual(f
.formfield().choices
, choices
)
193 def test_return_type(self
):
197 b2
= BooleanModel
.objects
.get(pk
=b
.pk
)
198 self
.assertTrue(isinstance(b2
.bfield
, bool))
199 self
.assertEqual(b2
.bfield
, True)
204 b4
= BooleanModel
.objects
.get(pk
=b3
.pk
)
205 self
.assertTrue(isinstance(b4
.bfield
, bool))
206 self
.assertEqual(b4
.bfield
, False)
208 b
= NullBooleanModel()
211 b2
= NullBooleanModel
.objects
.get(pk
=b
.pk
)
212 self
.assertTrue(isinstance(b2
.nbfield
, bool))
213 self
.assertEqual(b2
.nbfield
, True)
215 b3
= NullBooleanModel()
218 b4
= NullBooleanModel
.objects
.get(pk
=b3
.pk
)
219 self
.assertTrue(isinstance(b4
.nbfield
, bool))
220 self
.assertEqual(b4
.nbfield
, False)
222 # http://code.djangoproject.com/ticket/13293
223 # Verify that when an extra clause exists, the boolean
224 # conversions are applied with an offset
225 b5
= BooleanModel
.objects
.all().extra(
226 select
={'string_col': 'string'})[0]
227 self
.assertFalse(isinstance(b5
.pk
, bool))
229 def test_select_related(self
):
231 Test type of boolean fields when retrieved via select_related() (MySQL,
234 bmt
= BooleanModel
.objects
.create(bfield
=True)
235 bmf
= BooleanModel
.objects
.create(bfield
=False)
236 nbmt
= NullBooleanModel
.objects
.create(nbfield
=True)
237 nbmf
= NullBooleanModel
.objects
.create(nbfield
=False)
239 m1
= FksToBooleans
.objects
.create(bf
=bmt
, nbf
=nbmt
)
240 m2
= FksToBooleans
.objects
.create(bf
=bmf
, nbf
=nbmf
)
242 # Test select_related('fk_field_name')
243 ma
= FksToBooleans
.objects
.select_related('bf').get(pk
=m1
.id)
244 # verify types -- should't be 0/1
245 self
.assertIsInstance(ma
.bf
.bfield
, bool)
246 self
.assertIsInstance(ma
.nbf
.nbfield
, bool)
248 self
.assertEqual(ma
.bf
.bfield
, True)
249 self
.assertEqual(ma
.nbf
.nbfield
, True)
251 # Test select_related()
252 mb
= FksToBooleans
.objects
.select_related().get(pk
=m1
.id)
253 mc
= FksToBooleans
.objects
.select_related().get(pk
=m2
.id)
254 # verify types -- shouldn't be 0/1
255 self
.assertIsInstance(mb
.bf
.bfield
, bool)
256 self
.assertIsInstance(mb
.nbf
.nbfield
, bool)
257 self
.assertIsInstance(mc
.bf
.bfield
, bool)
258 self
.assertIsInstance(mc
.nbf
.nbfield
, bool)
260 self
.assertEqual(mb
.bf
.bfield
, True)
261 self
.assertEqual(mb
.nbf
.nbfield
, True)
262 self
.assertEqual(mc
.bf
.bfield
, False)
263 self
.assertEqual(mc
.nbf
.nbfield
, False)
266 class ChoicesTests(test
.TestCase
):
267 def test_choices_and_field_display(self
):
269 Check that get_choices and get_flatchoices interact with
270 get_FIELD_display to return the expected values (#7913).
272 self
.assertEqual(Whiz(c
=1).get_c_display(), 'First') # A nested value
273 self
.assertEqual(Whiz(c
=0).get_c_display(), 'Other') # A top level value
274 self
.assertEqual(Whiz(c
=9).get_c_display(), 9) # Invalid value
275 self
.assertEqual(Whiz(c
=None).get_c_display(), None) # Blank value
276 self
.assertEqual(Whiz(c
='').get_c_display(), '') # Empty value
278 class SlugFieldTests(test
.TestCase
):
279 def test_slugfield_max_length(self
):
281 Make sure SlugField honors max_length (#9706)
283 bs
= BigS
.objects
.create(s
= 'slug'*50)
284 bs
= BigS
.objects
.get(pk
=bs
.pk
)
285 self
.assertEqual(bs
.s
, 'slug'*50)
288 class ValidationTest(test
.TestCase
):
289 def test_charfield_raises_error_on_empty_string(self
):
290 f
= models
.CharField()
291 self
.assertRaises(ValidationError
, f
.clean
, "", None)
293 def test_charfield_cleans_empty_string_when_blank_true(self
):
294 f
= models
.CharField(blank
=True)
295 self
.assertEqual('', f
.clean('', None))
297 def test_integerfield_cleans_valid_string(self
):
298 f
= models
.IntegerField()
299 self
.assertEqual(2, f
.clean('2', None))
301 def test_integerfield_raises_error_on_invalid_intput(self
):
302 f
= models
.IntegerField()
303 self
.assertRaises(ValidationError
, f
.clean
, "a", None)
305 def test_charfield_with_choices_cleans_valid_choice(self
):
306 f
= models
.CharField(max_length
=1, choices
=[('a','A'), ('b','B')])
307 self
.assertEqual('a', f
.clean('a', None))
309 def test_charfield_with_choices_raises_error_on_invalid_choice(self
):
310 f
= models
.CharField(choices
=[('a','A'), ('b','B')])
311 self
.assertRaises(ValidationError
, f
.clean
, "not a", None)
313 def test_choices_validation_supports_named_groups(self
):
314 f
= models
.IntegerField(choices
=(('group',((10,'A'),(20,'B'))),(30,'C')))
315 self
.assertEqual(10, f
.clean(10, None))
317 def test_nullable_integerfield_raises_error_with_blank_false(self
):
318 f
= models
.IntegerField(null
=True, blank
=False)
319 self
.assertRaises(ValidationError
, f
.clean
, None, None)
321 def test_nullable_integerfield_cleans_none_on_null_and_blank_true(self
):
322 f
= models
.IntegerField(null
=True, blank
=True)
323 self
.assertEqual(None, f
.clean(None, None))
325 def test_integerfield_raises_error_on_empty_input(self
):
326 f
= models
.IntegerField(null
=False)
327 self
.assertRaises(ValidationError
, f
.clean
, None, None)
328 self
.assertRaises(ValidationError
, f
.clean
, '', None)
330 def test_integerfield_validates_zero_against_choices(self
):
331 f
= models
.IntegerField(choices
=((1, 1),))
332 self
.assertRaises(ValidationError
, f
.clean
, '0', None)
334 def test_charfield_raises_error_on_empty_input(self
):
335 f
= models
.CharField(null
=False)
336 self
.assertRaises(ValidationError
, f
.clean
, None, None)
338 def test_datefield_cleans_date(self
):
339 f
= models
.DateField()
340 self
.assertEqual(datetime
.date(2008, 10, 10), f
.clean('2008-10-10', None))
342 def test_boolean_field_doesnt_accept_empty_input(self
):
343 f
= models
.BooleanField()
344 self
.assertRaises(ValidationError
, f
.clean
, None, None)
347 class BigIntegerFieldTests(test
.TestCase
):
348 def test_limits(self
):
349 # Ensure that values that are right at the limits can be saved
350 # and then retrieved without corruption.
351 maxval
= 9223372036854775807
353 BigInt
.objects
.create(value
=maxval
)
354 qs
= BigInt
.objects
.filter(value__gte
=maxval
)
355 self
.assertEqual(qs
.count(), 1)
356 self
.assertEqual(qs
[0].value
, maxval
)
357 BigInt
.objects
.create(value
=minval
)
358 qs
= BigInt
.objects
.filter(value__lte
=minval
)
359 self
.assertEqual(qs
.count(), 1)
360 self
.assertEqual(qs
[0].value
, minval
)
362 def test_types(self
):
363 b
= BigInt(value
= 0)
364 self
.assertTrue(isinstance(b
.value
, six
.integer_types
))
366 self
.assertTrue(isinstance(b
.value
, six
.integer_types
))
367 b
= BigInt
.objects
.all()[0]
368 self
.assertTrue(isinstance(b
.value
, six
.integer_types
))
370 def test_coercing(self
):
371 BigInt
.objects
.create(value
='10')
372 b
= BigInt
.objects
.get(value
= '10')
373 self
.assertEqual(b
.value
, 10)
375 class TypeCoercionTests(test
.TestCase
):
377 Test that database lookups can accept the wrong types and convert
378 them with no error: especially on Postgres 8.3+ which does not do
379 automatic casting at the DB level. See #10015.
382 def test_lookup_integer_in_charfield(self
):
383 self
.assertEqual(Post
.objects
.filter(title
=9).count(), 0)
385 def test_lookup_integer_in_textfield(self
):
386 self
.assertEqual(Post
.objects
.filter(body
=24).count(), 0)
388 class FileFieldTests(unittest
.TestCase
):
389 def test_clearable(self
):
391 Test that FileField.save_form_data will clear its instance attribute
392 value if passed False.
395 d
= Document(myfile
='something.txt')
396 self
.assertEqual(d
.myfile
, 'something.txt')
397 field
= d
._meta
.get_field('myfile')
398 field
.save_form_data(d
, False)
399 self
.assertEqual(d
.myfile
, '')
401 def test_unchanged(self
):
403 Test that FileField.save_form_data considers None to mean "no change"
407 d
= Document(myfile
='something.txt')
408 self
.assertEqual(d
.myfile
, 'something.txt')
409 field
= d
._meta
.get_field('myfile')
410 field
.save_form_data(d
, None)
411 self
.assertEqual(d
.myfile
, 'something.txt')
413 def test_changed(self
):
415 Test that FileField.save_form_data, if passed a truthy value, updates
416 its instance attribute.
419 d
= Document(myfile
='something.txt')
420 self
.assertEqual(d
.myfile
, 'something.txt')
421 field
= d
._meta
.get_field('myfile')
422 field
.save_form_data(d
, 'else.txt')
423 self
.assertEqual(d
.myfile
, 'else.txt')
426 class PrepValueTest(test
.TestCase
):
427 def test_AutoField(self
):
428 self
.assertIsInstance(AutoField(primary_key
=True).get_prep_value(1), int)
430 @unittest.skipIf(six
.PY3
, "Python 3 has no `long` type.")
431 def test_BigIntegerField(self
):
432 self
.assertIsInstance(BigIntegerField().get_prep_value(long(9999999999999999999)), long)
434 def test_BooleanField(self
):
435 self
.assertIsInstance(BooleanField().get_prep_value(True), bool)
437 def test_CharField(self
):
438 self
.assertIsInstance(CharField().get_prep_value(''), six
.text_type
)
439 self
.assertIsInstance(CharField().get_prep_value(0), six
.text_type
)
441 def test_CommaSeparatedIntegerField(self
):
442 self
.assertIsInstance(CommaSeparatedIntegerField().get_prep_value('1,2'), six
.text_type
)
443 self
.assertIsInstance(CommaSeparatedIntegerField().get_prep_value(0), six
.text_type
)
445 def test_DateField(self
):
446 self
.assertIsInstance(DateField().get_prep_value(datetime
.date
.today()), datetime
.date
)
448 def test_DateTimeField(self
):
449 self
.assertIsInstance(DateTimeField().get_prep_value(datetime
.datetime
.now()), datetime
.datetime
)
451 def test_DecimalField(self
):
452 self
.assertIsInstance(DecimalField().get_prep_value(Decimal('1.2')), Decimal
)
454 def test_EmailField(self
):
455 self
.assertIsInstance(EmailField().get_prep_value('mailbox@domain.com'), six
.text_type
)
457 def test_FileField(self
):
458 self
.assertIsInstance(FileField().get_prep_value('filename.ext'), six
.text_type
)
459 self
.assertIsInstance(FileField().get_prep_value(0), six
.text_type
)
461 def test_FilePathField(self
):
462 self
.assertIsInstance(FilePathField().get_prep_value('tests.py'), six
.text_type
)
463 self
.assertIsInstance(FilePathField().get_prep_value(0), six
.text_type
)
465 def test_FloatField(self
):
466 self
.assertIsInstance(FloatField().get_prep_value(1.2), float)
468 def test_ImageField(self
):
469 self
.assertIsInstance(ImageField().get_prep_value('filename.ext'), six
.text_type
)
471 def test_IntegerField(self
):
472 self
.assertIsInstance(IntegerField().get_prep_value(1), int)
474 def test_IPAddressField(self
):
475 self
.assertIsInstance(IPAddressField().get_prep_value('127.0.0.1'), six
.text_type
)
476 self
.assertIsInstance(IPAddressField().get_prep_value(0), six
.text_type
)
478 def test_GenericIPAddressField(self
):
479 self
.assertIsInstance(GenericIPAddressField().get_prep_value('127.0.0.1'), six
.text_type
)
480 self
.assertIsInstance(GenericIPAddressField().get_prep_value(0), six
.text_type
)
482 def test_NullBooleanField(self
):
483 self
.assertIsInstance(NullBooleanField().get_prep_value(True), bool)
485 def test_PositiveIntegerField(self
):
486 self
.assertIsInstance(PositiveIntegerField().get_prep_value(1), int)
488 def test_PositiveSmallIntegerField(self
):
489 self
.assertIsInstance(PositiveSmallIntegerField().get_prep_value(1), int)
491 def test_SlugField(self
):
492 self
.assertIsInstance(SlugField().get_prep_value('slug'), six
.text_type
)
493 self
.assertIsInstance(SlugField().get_prep_value(0), six
.text_type
)
495 def test_SmallIntegerField(self
):
496 self
.assertIsInstance(SmallIntegerField().get_prep_value(1), int)
498 def test_TextField(self
):
499 self
.assertIsInstance(TextField().get_prep_value('Abc'), six
.text_type
)
500 self
.assertIsInstance(TextField().get_prep_value(0), six
.text_type
)
502 def test_TimeField(self
):
503 self
.assertIsInstance(
504 TimeField().get_prep_value(datetime
.datetime
.now().time()),
507 def test_URLField(self
):
508 self
.assertIsInstance(URLField().get_prep_value('http://domain.com'), six
.text_type
)