parts/django/tests/regressiontests/model_fields/tests.py
changeset 307 c6bca38c1cbf
equal deleted inserted replaced
306:5ff1fc726848 307:c6bca38c1cbf
       
     1 import datetime
       
     2 import unittest
       
     3 from decimal import Decimal
       
     4 
       
     5 import django.test
       
     6 from django import forms
       
     7 from django.db import models
       
     8 from django.core.exceptions import ValidationError
       
     9 
       
    10 from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel
       
    11 
       
    12 # If PIL available, do these tests.
       
    13 if Image:
       
    14     from imagefield import \
       
    15             ImageFieldTests, \
       
    16             ImageFieldTwoDimensionsTests, \
       
    17             ImageFieldNoDimensionsTests, \
       
    18             ImageFieldOneDimensionTests, \
       
    19             ImageFieldDimensionsFirstTests, \
       
    20             ImageFieldUsingFileTests, \
       
    21             TwoImageFieldTests
       
    22 
       
    23 
       
    24 class BasicFieldTests(django.test.TestCase):
       
    25     def test_show_hidden_initial(self):
       
    26         """
       
    27         Regression test for #12913. Make sure fields with choices respect
       
    28         show_hidden_initial as a kwarg to models.Field.formfield()
       
    29         """
       
    30         choices = [(0, 0), (1, 1)]
       
    31         model_field = models.Field(choices=choices)
       
    32         form_field = model_field.formfield(show_hidden_initial=True)
       
    33         self.assertTrue(form_field.show_hidden_initial)
       
    34 
       
    35         form_field = model_field.formfield(show_hidden_initial=False)
       
    36         self.assertFalse(form_field.show_hidden_initial)
       
    37 
       
    38     def test_nullbooleanfield_blank(self):
       
    39         """
       
    40         Regression test for #13071: NullBooleanField should not throw
       
    41         a validation error when given a value of None.
       
    42 
       
    43         """
       
    44         nullboolean = NullBooleanModel(nbfield=None)
       
    45         try:
       
    46             nullboolean.full_clean()
       
    47         except ValidationError, e:
       
    48             self.fail("NullBooleanField failed validation with value of None: %s" % e.messages)
       
    49 
       
    50 class DecimalFieldTests(django.test.TestCase):
       
    51     def test_to_python(self):
       
    52         f = models.DecimalField(max_digits=4, decimal_places=2)
       
    53         self.assertEqual(f.to_python(3), Decimal("3"))
       
    54         self.assertEqual(f.to_python("3.14"), Decimal("3.14"))
       
    55         self.assertRaises(ValidationError, f.to_python, "abc")
       
    56 
       
    57     def test_default(self):
       
    58         f = models.DecimalField(default=Decimal("0.00"))
       
    59         self.assertEqual(f.get_default(), Decimal("0.00"))
       
    60 
       
    61     def test_format(self):
       
    62         f = models.DecimalField(max_digits=5, decimal_places=1)
       
    63         self.assertEqual(f._format(f.to_python(2)), u'2.0')
       
    64         self.assertEqual(f._format(f.to_python('2.6')), u'2.6')
       
    65         self.assertEqual(f._format(None), None)
       
    66 
       
    67     def test_get_db_prep_lookup(self):
       
    68         from django.db import connection
       
    69         f = models.DecimalField(max_digits=5, decimal_places=1)
       
    70         self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
       
    71 
       
    72     def test_filter_with_strings(self):
       
    73         """
       
    74         We should be able to filter decimal fields using strings (#8023)
       
    75         """
       
    76         Foo.objects.create(id=1, a='abc', d=Decimal("12.34"))
       
    77         self.assertEqual(list(Foo.objects.filter(d=u'1.23')), [])
       
    78 
       
    79     def test_save_without_float_conversion(self):
       
    80         """
       
    81         Ensure decimals don't go through a corrupting float conversion during
       
    82         save (#5079).
       
    83         """
       
    84         bd = BigD(d="12.9")
       
    85         bd.save()
       
    86         bd = BigD.objects.get(pk=bd.pk)
       
    87         self.assertEqual(bd.d, Decimal("12.9"))
       
    88 
       
    89     def test_lookup_really_big_value(self):
       
    90         """
       
    91         Ensure that really big values can be used in a filter statement, even
       
    92         with older Python versions.
       
    93         """
       
    94         # This should not crash. That counts as a win for our purposes.
       
    95         Foo.objects.filter(d__gte=100000000000)
       
    96 
       
    97 class ForeignKeyTests(django.test.TestCase):
       
    98     def test_callable_default(self):
       
    99         """Test the use of a lazy callable for ForeignKey.default"""
       
   100         a = Foo.objects.create(id=1, a='abc', d=Decimal("12.34"))
       
   101         b = Bar.objects.create(b="bcd")
       
   102         self.assertEqual(b.a, a)
       
   103 
       
   104 class DateTimeFieldTests(unittest.TestCase):
       
   105     def test_datetimefield_to_python_usecs(self):
       
   106         """DateTimeField.to_python should support usecs"""
       
   107         f = models.DateTimeField()
       
   108         self.assertEqual(f.to_python('2001-01-02 03:04:05.000006'),
       
   109                          datetime.datetime(2001, 1, 2, 3, 4, 5, 6))
       
   110         self.assertEqual(f.to_python('2001-01-02 03:04:05.999999'),
       
   111                          datetime.datetime(2001, 1, 2, 3, 4, 5, 999999))
       
   112 
       
   113     def test_timefield_to_python_usecs(self):
       
   114         """TimeField.to_python should support usecs"""
       
   115         f = models.TimeField()
       
   116         self.assertEqual(f.to_python('01:02:03.000004'),
       
   117                          datetime.time(1, 2, 3, 4))
       
   118         self.assertEqual(f.to_python('01:02:03.999999'),
       
   119                          datetime.time(1, 2, 3, 999999))
       
   120 
       
   121 class BooleanFieldTests(unittest.TestCase):
       
   122     def _test_get_db_prep_lookup(self, f):
       
   123         from django.db import connection
       
   124         self.assertEqual(f.get_db_prep_lookup('exact', True, connection=connection), [True])
       
   125         self.assertEqual(f.get_db_prep_lookup('exact', '1', connection=connection), [True])
       
   126         self.assertEqual(f.get_db_prep_lookup('exact', 1, connection=connection), [True])
       
   127         self.assertEqual(f.get_db_prep_lookup('exact', False, connection=connection), [False])
       
   128         self.assertEqual(f.get_db_prep_lookup('exact', '0', connection=connection), [False])
       
   129         self.assertEqual(f.get_db_prep_lookup('exact', 0, connection=connection), [False])
       
   130         self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
       
   131 
       
   132     def _test_to_python(self, f):
       
   133         self.assertTrue(f.to_python(1) is True)
       
   134         self.assertTrue(f.to_python(0) is False)
       
   135 
       
   136     def test_booleanfield_get_db_prep_lookup(self):
       
   137         self._test_get_db_prep_lookup(models.BooleanField())
       
   138 
       
   139     def test_nullbooleanfield_get_db_prep_lookup(self):
       
   140         self._test_get_db_prep_lookup(models.NullBooleanField())
       
   141 
       
   142     def test_booleanfield_to_python(self):
       
   143         self._test_to_python(models.BooleanField())
       
   144 
       
   145     def test_nullbooleanfield_to_python(self):
       
   146         self._test_to_python(models.NullBooleanField())
       
   147 
       
   148     def test_booleanfield_choices_blank(self):
       
   149         """
       
   150         Test that BooleanField with choices and defaults doesn't generate a
       
   151         formfield with the blank option (#9640, #10549).
       
   152         """
       
   153         choices = [(1, u'Si'), (2, 'No')]
       
   154         f = models.BooleanField(choices=choices, default=1, null=True)
       
   155         self.assertEqual(f.formfield().choices, [('', '---------')] + choices)
       
   156 
       
   157         f = models.BooleanField(choices=choices, default=1, null=False)
       
   158         self.assertEqual(f.formfield().choices, choices)
       
   159 
       
   160     def test_return_type(self):
       
   161         b = BooleanModel()
       
   162         b.bfield = True
       
   163         b.save()
       
   164         b2 = BooleanModel.objects.get(pk=b.pk)
       
   165         self.assertTrue(isinstance(b2.bfield, bool))
       
   166         self.assertEqual(b2.bfield, True)
       
   167 
       
   168         b3 = BooleanModel()
       
   169         b3.bfield = False
       
   170         b3.save()
       
   171         b4 = BooleanModel.objects.get(pk=b3.pk)
       
   172         self.assertTrue(isinstance(b4.bfield, bool))
       
   173         self.assertEqual(b4.bfield, False)
       
   174 
       
   175         b = NullBooleanModel()
       
   176         b.nbfield = True
       
   177         b.save()
       
   178         b2 = NullBooleanModel.objects.get(pk=b.pk)
       
   179         self.assertTrue(isinstance(b2.nbfield, bool))
       
   180         self.assertEqual(b2.nbfield, True)
       
   181 
       
   182         b3 = NullBooleanModel()
       
   183         b3.nbfield = False
       
   184         b3.save()
       
   185         b4 = NullBooleanModel.objects.get(pk=b3.pk)
       
   186         self.assertTrue(isinstance(b4.nbfield, bool))
       
   187         self.assertEqual(b4.nbfield, False)
       
   188 
       
   189         # http://code.djangoproject.com/ticket/13293
       
   190         # Verify that when an extra clause exists, the boolean
       
   191         # conversions are applied with an offset
       
   192         b5 = BooleanModel.objects.all().extra(
       
   193             select={'string_length': 'LENGTH(string)'})[0]
       
   194         self.assertFalse(isinstance(b5.pk, bool))
       
   195 
       
   196 class ChoicesTests(django.test.TestCase):
       
   197     def test_choices_and_field_display(self):
       
   198         """
       
   199         Check that get_choices and get_flatchoices interact with
       
   200         get_FIELD_display to return the expected values (#7913).
       
   201         """
       
   202         self.assertEqual(Whiz(c=1).get_c_display(), 'First')    # A nested value
       
   203         self.assertEqual(Whiz(c=0).get_c_display(), 'Other')    # A top level value
       
   204         self.assertEqual(Whiz(c=9).get_c_display(), 9)          # Invalid value
       
   205         self.assertEqual(Whiz(c=None).get_c_display(), None)    # Blank value
       
   206         self.assertEqual(Whiz(c='').get_c_display(), '')        # Empty value
       
   207 
       
   208 class SlugFieldTests(django.test.TestCase):
       
   209     def test_slugfield_max_length(self):
       
   210         """
       
   211         Make sure SlugField honors max_length (#9706)
       
   212         """
       
   213         bs = BigS.objects.create(s = 'slug'*50)
       
   214         bs = BigS.objects.get(pk=bs.pk)
       
   215         self.assertEqual(bs.s, 'slug'*50)
       
   216 
       
   217 
       
   218 class ValidationTest(django.test.TestCase):
       
   219     def test_charfield_raises_error_on_empty_string(self):
       
   220         f = models.CharField()
       
   221         self.assertRaises(ValidationError, f.clean, "", None)
       
   222 
       
   223     def test_charfield_cleans_empty_string_when_blank_true(self):
       
   224         f = models.CharField(blank=True)
       
   225         self.assertEqual('', f.clean('', None))
       
   226 
       
   227     def test_integerfield_cleans_valid_string(self):
       
   228         f = models.IntegerField()
       
   229         self.assertEqual(2, f.clean('2', None))
       
   230 
       
   231     def test_integerfield_raises_error_on_invalid_intput(self):
       
   232         f = models.IntegerField()
       
   233         self.assertRaises(ValidationError, f.clean, "a", None)
       
   234 
       
   235     def test_charfield_with_choices_cleans_valid_choice(self):
       
   236         f = models.CharField(max_length=1, choices=[('a','A'), ('b','B')])
       
   237         self.assertEqual('a', f.clean('a', None))
       
   238 
       
   239     def test_charfield_with_choices_raises_error_on_invalid_choice(self):
       
   240         f = models.CharField(choices=[('a','A'), ('b','B')])
       
   241         self.assertRaises(ValidationError, f.clean, "not a", None)
       
   242 
       
   243     def test_choices_validation_supports_named_groups(self):
       
   244         f = models.IntegerField(choices=(('group',((10,'A'),(20,'B'))),(30,'C')))
       
   245         self.assertEqual(10, f.clean(10, None))
       
   246 
       
   247     def test_nullable_integerfield_raises_error_with_blank_false(self):
       
   248         f = models.IntegerField(null=True, blank=False)
       
   249         self.assertRaises(ValidationError, f.clean, None, None)
       
   250 
       
   251     def test_nullable_integerfield_cleans_none_on_null_and_blank_true(self):
       
   252         f = models.IntegerField(null=True, blank=True)
       
   253         self.assertEqual(None, f.clean(None, None))
       
   254 
       
   255     def test_integerfield_raises_error_on_empty_input(self):
       
   256         f = models.IntegerField(null=False)
       
   257         self.assertRaises(ValidationError, f.clean, None, None)
       
   258         self.assertRaises(ValidationError, f.clean, '', None)
       
   259 
       
   260     def test_charfield_raises_error_on_empty_input(self):
       
   261         f = models.CharField(null=False)
       
   262         self.assertRaises(ValidationError, f.clean, None, None)
       
   263 
       
   264     def test_datefield_cleans_date(self):
       
   265         f = models.DateField()
       
   266         self.assertEqual(datetime.date(2008, 10, 10), f.clean('2008-10-10', None))
       
   267 
       
   268     def test_boolean_field_doesnt_accept_empty_input(self):
       
   269         f = models.BooleanField()
       
   270         self.assertRaises(ValidationError, f.clean, None, None)
       
   271 
       
   272 
       
   273 class BigIntegerFieldTests(django.test.TestCase):
       
   274     def test_limits(self):
       
   275         # Ensure that values that are right at the limits can be saved
       
   276         # and then retrieved without corruption.
       
   277         maxval = 9223372036854775807
       
   278         minval = -maxval - 1
       
   279         BigInt.objects.create(value=maxval)
       
   280         qs = BigInt.objects.filter(value__gte=maxval)
       
   281         self.assertEqual(qs.count(), 1)
       
   282         self.assertEqual(qs[0].value, maxval)
       
   283         BigInt.objects.create(value=minval)
       
   284         qs = BigInt.objects.filter(value__lte=minval)
       
   285         self.assertEqual(qs.count(), 1)
       
   286         self.assertEqual(qs[0].value, minval)
       
   287 
       
   288     def test_types(self):
       
   289         b = BigInt(value = 0)
       
   290         self.assertTrue(isinstance(b.value, (int, long)))
       
   291         b.save()
       
   292         self.assertTrue(isinstance(b.value, (int, long)))
       
   293         b = BigInt.objects.all()[0]
       
   294         self.assertTrue(isinstance(b.value, (int, long)))
       
   295 
       
   296     def test_coercing(self):
       
   297         BigInt.objects.create(value ='10')
       
   298         b = BigInt.objects.get(value = '10')
       
   299         self.assertEqual(b.value, 10)
       
   300 
       
   301 class TypeCoercionTests(django.test.TestCase):
       
   302     """
       
   303     Test that database lookups can accept the wrong types and convert
       
   304     them with no error: especially on Postgres 8.3+ which does not do
       
   305     automatic casting at the DB level. See #10015.
       
   306 
       
   307     """
       
   308     def test_lookup_integer_in_charfield(self):
       
   309         self.assertEquals(Post.objects.filter(title=9).count(), 0)
       
   310 
       
   311     def test_lookup_integer_in_textfield(self):
       
   312         self.assertEquals(Post.objects.filter(body=24).count(), 0)
       
   313