Selaa lähdekoodia

Split model_fields tests into different files.

Tim Graham 9 vuotta sitten
vanhempi
commit
3c1b572f18

+ 1 - 1
tests/model_fields/models.py

@@ -121,7 +121,7 @@ class NullBooleanModel(models.Model):
 
 
 class BooleanModel(models.Model):
-    bfield = models.BooleanField(default=None)
+    bfield = models.BooleanField()
     string = models.CharField(max_length=10, default='abc')
 
 

+ 28 - 0
tests/model_fields/test_binaryfield.py

@@ -0,0 +1,28 @@
+from django.core.exceptions import ValidationError
+from django.test import TestCase
+from django.utils import six
+
+from .models import DataModel
+
+
+class BinaryFieldTests(TestCase):
+    binary_data = b'\x00\x46\xFE'
+
+    def test_set_and_retrieve(self):
+        data_set = (self.binary_data, six.memoryview(self.binary_data))
+        for bdata in data_set:
+            dm = DataModel(data=bdata)
+            dm.save()
+            dm = DataModel.objects.get(pk=dm.pk)
+            self.assertEqual(bytes(dm.data), bytes(bdata))
+            # Resave (=update)
+            dm.save()
+            dm = DataModel.objects.get(pk=dm.pk)
+            self.assertEqual(bytes(dm.data), bytes(bdata))
+            # Test default value
+            self.assertEqual(bytes(dm.short_data), b'\x08')
+
+    def test_max_length(self):
+        dm = DataModel(short_data=self.binary_data * 4)
+        with self.assertRaises(ValidationError):
+            dm.full_clean()

+ 119 - 0
tests/model_fields/test_booleanfield.py

@@ -0,0 +1,119 @@
+from django.core.exceptions import ValidationError
+from django.db import IntegrityError, connection, models, transaction
+from django.test import SimpleTestCase, TestCase
+
+from .models import BooleanModel, FksToBooleans, NullBooleanModel
+
+
+class BooleanFieldTests(TestCase):
+    def _test_get_db_prep_lookup(self, f):
+        self.assertEqual(f.get_db_prep_lookup('exact', True, connection=connection), [True])
+        self.assertEqual(f.get_db_prep_lookup('exact', '1', connection=connection), [True])
+        self.assertEqual(f.get_db_prep_lookup('exact', 1, connection=connection), [True])
+        self.assertEqual(f.get_db_prep_lookup('exact', False, connection=connection), [False])
+        self.assertEqual(f.get_db_prep_lookup('exact', '0', connection=connection), [False])
+        self.assertEqual(f.get_db_prep_lookup('exact', 0, connection=connection), [False])
+        self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
+
+    def _test_to_python(self, f):
+        self.assertIs(f.to_python(1), True)
+        self.assertIs(f.to_python(0), False)
+
+    def test_booleanfield_get_db_prep_lookup(self):
+        self._test_get_db_prep_lookup(models.BooleanField())
+
+    def test_nullbooleanfield_get_db_prep_lookup(self):
+        self._test_get_db_prep_lookup(models.NullBooleanField())
+
+    def test_booleanfield_to_python(self):
+        self._test_to_python(models.BooleanField())
+
+    def test_nullbooleanfield_to_python(self):
+        self._test_to_python(models.NullBooleanField())
+
+    def test_booleanfield_choices_blank(self):
+        """
+        BooleanField with choices and defaults doesn't generate a formfield
+        with the blank option (#9640, #10549).
+        """
+        choices = [(1, 'Si'), (2, 'No')]
+        f = models.BooleanField(choices=choices, default=1, null=False)
+        self.assertEqual(f.formfield().choices, choices)
+
+    def test_return_type(self):
+        b = BooleanModel.objects.create(bfield=True)
+        b.refresh_from_db()
+        self.assertEqual(b.bfield, True)
+
+        b2 = BooleanModel.objects.create(bfield=False)
+        b2.refresh_from_db()
+        self.assertEqual(b2.bfield, False)
+
+        b3 = NullBooleanModel.objects.create(nbfield=True)
+        b3.refresh_from_db()
+        self.assertEqual(b3.nbfield, True)
+
+        b4 = NullBooleanModel.objects.create(nbfield=False)
+        b4.refresh_from_db()
+        self.assertEqual(b4.nbfield, False)
+
+        # When an extra clause exists, the boolean conversions are applied with
+        # an offset (#13293).
+        b5 = BooleanModel.objects.all().extra(select={'string_col': 'string'})[0]
+        self.assertNotIsInstance(b5.pk, bool)
+
+    def test_select_related(self):
+        """
+        Boolean fields retrieved via select_related() should return booleans.
+        """
+        bmt = BooleanModel.objects.create(bfield=True)
+        bmf = BooleanModel.objects.create(bfield=False)
+        nbmt = NullBooleanModel.objects.create(nbfield=True)
+        nbmf = NullBooleanModel.objects.create(nbfield=False)
+        m1 = FksToBooleans.objects.create(bf=bmt, nbf=nbmt)
+        m2 = FksToBooleans.objects.create(bf=bmf, nbf=nbmf)
+
+        # select_related('fk_field_name')
+        ma = FksToBooleans.objects.select_related('bf').get(pk=m1.id)
+        self.assertEqual(ma.bf.bfield, True)
+        self.assertEqual(ma.nbf.nbfield, True)
+
+        # select_related()
+        mb = FksToBooleans.objects.select_related().get(pk=m1.id)
+        mc = FksToBooleans.objects.select_related().get(pk=m2.id)
+        self.assertEqual(mb.bf.bfield, True)
+        self.assertEqual(mb.nbf.nbfield, True)
+        self.assertEqual(mc.bf.bfield, False)
+        self.assertEqual(mc.nbf.nbfield, False)
+
+    def test_null_default(self):
+        """
+        A BooleanField defaults to None, which isn't a valid value (#15124).
+        """
+        boolean_field = BooleanModel._meta.get_field('bfield')
+        self.assertFalse(boolean_field.has_default())
+        b = BooleanModel()
+        self.assertIsNone(b.bfield)
+        with transaction.atomic():
+            with self.assertRaises(IntegrityError):
+                b.save()
+
+        nb = NullBooleanModel()
+        self.assertIsNone(nb.nbfield)
+        nb.save()  # no error
+
+
+class ValidationTest(SimpleTestCase):
+
+    def test_boolean_field_doesnt_accept_empty_input(self):
+        f = models.BooleanField()
+        with self.assertRaises(ValidationError):
+            f.clean(None, None)
+
+    def test_nullbooleanfield_blank(self):
+        """
+        NullBooleanField shouldn't throw a validation error when given a value
+        of None.
+        """
+        nullboolean = NullBooleanModel(nbfield=None)
+        nullboolean.full_clean()

+ 59 - 0
tests/model_fields/test_charfield.py

@@ -0,0 +1,59 @@
+from django.core.exceptions import ValidationError
+from django.db import models
+from django.test import SimpleTestCase, TestCase
+from django.utils.functional import lazy
+
+from .models import Post
+
+
+class TestCharField(TestCase):
+
+    def test_max_length_passed_to_formfield(self):
+        """
+        CharField passes its max_length attribute to form fields created using
+        the formfield() method.
+        """
+        cf1 = models.CharField()
+        cf2 = models.CharField(max_length=1234)
+        self.assertIsNone(cf1.formfield().max_length)
+        self.assertEqual(1234, cf2.formfield().max_length)
+
+    def test_lookup_integer_in_charfield(self):
+        self.assertEqual(Post.objects.filter(title=9).count(), 0)
+
+
+class ValidationTests(SimpleTestCase):
+
+    def test_charfield_raises_error_on_empty_string(self):
+        f = models.CharField()
+        with self.assertRaises(ValidationError):
+            f.clean('', None)
+
+    def test_charfield_cleans_empty_string_when_blank_true(self):
+        f = models.CharField(blank=True)
+        self.assertEqual('', f.clean('', None))
+
+    def test_charfield_with_choices_cleans_valid_choice(self):
+        f = models.CharField(max_length=1, choices=[('a', 'A'), ('b', 'B')])
+        self.assertEqual('a', f.clean('a', None))
+
+    def test_charfield_with_choices_raises_error_on_invalid_choice(self):
+        f = models.CharField(choices=[('a', 'A'), ('b', 'B')])
+        with self.assertRaises(ValidationError):
+            f.clean('not a', None)
+
+    def test_charfield_get_choices_with_blank_defined(self):
+        f = models.CharField(choices=[('', '<><>'), ('a', 'A')])
+        self.assertEqual(f.get_choices(True), [('', '<><>'), ('a', 'A')])
+
+    def test_charfield_get_choices_doesnt_evaluate_lazy_strings(self):
+        # Regression test for #23098
+        # Will raise ZeroDivisionError if lazy is evaluated
+        lazy_func = lazy(lambda x: 0 / 0, int)
+        f = models.CharField(choices=[(lazy_func('group'), (('a', 'A'), ('b', 'B')))])
+        self.assertEqual(f.get_choices(True)[0], ('', '---------'))
+
+    def test_charfield_raises_error_on_empty_input(self):
+        f = models.CharField(null=False)
+        with self.assertRaises(ValidationError):
+            f.clean(None, None)

+ 22 - 0
tests/model_fields/test_custom_fields.py

@@ -0,0 +1,22 @@
+from django.db import connection, models
+from django.test import SimpleTestCase
+
+
+class CustomFieldTests(SimpleTestCase):
+
+    def test_get_prep_value_count(self):
+        """
+        Field values are not prepared twice in get_db_prep_lookup() (#14786).
+        """
+        class NoopField(models.TextField):
+            def __init__(self, *args, **kwargs):
+                self.prep_value_count = 0
+                super(NoopField, self).__init__(*args, **kwargs)
+
+            def get_prep_value(self, value):
+                self.prep_value_count += 1
+                return super(NoopField, self).get_prep_value(value)
+
+        field = NoopField()
+        field.get_db_prep_lookup('exact', 'TEST', connection=connection, prepared=False)
+        self.assertEqual(field.prep_value_count, 1)

+ 77 - 0
tests/model_fields/test_datetimefield.py

@@ -0,0 +1,77 @@
+import datetime
+
+from django.db import models
+from django.test import (
+    SimpleTestCase, TestCase, override_settings, skipUnlessDBFeature,
+)
+from django.test.utils import requires_tz_support
+from django.utils import timezone
+
+from .models import DateTimeModel
+
+
+class DateTimeFieldTests(TestCase):
+
+    def test_datetimefield_to_python_microseconds(self):
+        """DateTimeField.to_python() supports microseconds."""
+        f = models.DateTimeField()
+        self.assertEqual(f.to_python('2001-01-02 03:04:05.000006'), datetime.datetime(2001, 1, 2, 3, 4, 5, 6))
+        self.assertEqual(f.to_python('2001-01-02 03:04:05.999999'), datetime.datetime(2001, 1, 2, 3, 4, 5, 999999))
+
+    def test_timefield_to_python_microseconds(self):
+        """TimeField.to_python() supports microseconds."""
+        f = models.TimeField()
+        self.assertEqual(f.to_python('01:02:03.000004'), datetime.time(1, 2, 3, 4))
+        self.assertEqual(f.to_python('01:02:03.999999'), datetime.time(1, 2, 3, 999999))
+
+    @skipUnlessDBFeature('supports_microsecond_precision')
+    def test_datetimes_save_completely(self):
+        dat = datetime.date(2014, 3, 12)
+        datetim = datetime.datetime(2014, 3, 12, 21, 22, 23, 240000)
+        tim = datetime.time(21, 22, 23, 240000)
+        DateTimeModel.objects.create(d=dat, dt=datetim, t=tim)
+        obj = DateTimeModel.objects.first()
+        self.assertTrue(obj)
+        self.assertEqual(obj.d, dat)
+        self.assertEqual(obj.dt, datetim)
+        self.assertEqual(obj.t, tim)
+
+    @override_settings(USE_TZ=False)
+    def test_lookup_date_without_use_tz(self):
+        d = datetime.date(2014, 3, 12)
+        dt1 = datetime.datetime(2014, 3, 12, 21, 22, 23, 240000)
+        dt2 = datetime.datetime(2014, 3, 11, 21, 22, 23, 240000)
+        t = datetime.time(21, 22, 23, 240000)
+        m = DateTimeModel.objects.create(d=d, dt=dt1, t=t)
+        # Other model with different datetime.
+        DateTimeModel.objects.create(d=d, dt=dt2, t=t)
+        self.assertEqual(m, DateTimeModel.objects.get(dt__date=d))
+
+    @requires_tz_support
+    @skipUnlessDBFeature('has_zoneinfo_database')
+    @override_settings(USE_TZ=True, TIME_ZONE='America/Vancouver')
+    def test_lookup_date_with_use_tz(self):
+        d = datetime.date(2014, 3, 12)
+        # The following is equivalent to UTC 2014-03-12 18:34:23.24000.
+        dt1 = datetime.datetime(2014, 3, 12, 10, 22, 23, 240000, tzinfo=timezone.get_current_timezone())
+        # The following is equivalent to UTC 2014-03-13 05:34:23.24000.
+        dt2 = datetime.datetime(2014, 3, 12, 21, 22, 23, 240000, tzinfo=timezone.get_current_timezone())
+        t = datetime.time(21, 22, 23, 240000)
+        m1 = DateTimeModel.objects.create(d=d, dt=dt1, t=t)
+        m2 = DateTimeModel.objects.create(d=d, dt=dt2, t=t)
+        # In Vancouver, we expect both results.
+        self.assertQuerysetEqual(
+            DateTimeModel.objects.filter(dt__date=d),
+            [repr(m1), repr(m2)],
+            ordered=False
+        )
+        with self.settings(TIME_ZONE='UTC'):
+            # But in UTC, the __date only matches one of them.
+            self.assertQuerysetEqual(DateTimeModel.objects.filter(dt__date=d), [repr(m1)])
+
+
+class ValidationTest(SimpleTestCase):
+
+    def test_datefield_cleans_date(self):
+        f = models.DateField()
+        self.assertEqual(datetime.date(2008, 10, 10), f.clean('2008-10-10', None))

+ 74 - 0
tests/model_fields/test_decimalfield.py

@@ -0,0 +1,74 @@
+from decimal import Decimal
+
+from django.core import validators
+from django.core.exceptions import ValidationError
+from django.db import connection, models
+from django.test import TestCase
+
+from .models import BigD, Foo
+
+
+class DecimalFieldTests(TestCase):
+
+    def test_to_python(self):
+        f = models.DecimalField(max_digits=4, decimal_places=2)
+        self.assertEqual(f.to_python(3), Decimal('3'))
+        self.assertEqual(f.to_python('3.14'), Decimal('3.14'))
+        with self.assertRaises(ValidationError):
+            f.to_python('abc')
+
+    def test_default(self):
+        f = models.DecimalField(default=Decimal('0.00'))
+        self.assertEqual(f.get_default(), Decimal('0.00'))
+
+    def test_format(self):
+        f = models.DecimalField(max_digits=5, decimal_places=1)
+        self.assertEqual(f._format(f.to_python(2)), '2.0')
+        self.assertEqual(f._format(f.to_python('2.6')), '2.6')
+        self.assertEqual(f._format(None), None)
+
+    def test_get_db_prep_lookup(self):
+        f = models.DecimalField(max_digits=5, decimal_places=1)
+        self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
+
+    def test_filter_with_strings(self):
+        """
+        Should be able to filter decimal fields using strings (#8023).
+        """
+        foo = Foo.objects.create(a='abc', d=Decimal('12.34'))
+        self.assertEqual(list(Foo.objects.filter(d='12.34')), [foo])
+
+    def test_save_without_float_conversion(self):
+        """
+        Ensure decimals don't go through a corrupting float conversion during
+        save (#5079).
+        """
+        bd = BigD(d='12.9')
+        bd.save()
+        bd = BigD.objects.get(pk=bd.pk)
+        self.assertEqual(bd.d, Decimal('12.9'))
+
+    def test_lookup_really_big_value(self):
+        """
+        Really big values can be used in a filter statement.
+        """
+        # This should not crash.
+        Foo.objects.filter(d__gte=100000000000)
+
+    def test_max_digits_validation(self):
+        field = models.DecimalField(max_digits=2)
+        expected_message = validators.DecimalValidator.messages['max_digits'] % {'max': 2}
+        with self.assertRaisesMessage(ValidationError, expected_message):
+            field.clean(100, None)
+
+    def test_max_decimal_places_validation(self):
+        field = models.DecimalField(decimal_places=1)
+        expected_message = validators.DecimalValidator.messages['max_decimal_places'] % {'max': 1}
+        with self.assertRaisesMessage(ValidationError, expected_message):
+            field.clean(Decimal('0.99'), None)
+
+    def test_max_whole_digits_validation(self):
+        field = models.DecimalField(max_digits=3, decimal_places=1)
+        expected_message = validators.DecimalValidator.messages['max_whole_digits'] % {'max': 2}
+        with self.assertRaisesMessage(ValidationError, expected_message):
+            field.clean(Decimal('999'), None)

+ 52 - 0
tests/model_fields/test_filefield.py

@@ -0,0 +1,52 @@
+from django.test import TestCase
+
+from .models import Document
+
+
+class FileFieldTests(TestCase):
+
+    def test_clearable(self):
+        """
+        FileField.save_form_data() will clear its instance attribute value if
+        passed False.
+        """
+        d = Document(myfile='something.txt')
+        self.assertEqual(d.myfile, 'something.txt')
+        field = d._meta.get_field('myfile')
+        field.save_form_data(d, False)
+        self.assertEqual(d.myfile, '')
+
+    def test_unchanged(self):
+        """
+        FileField.save_form_data() considers None to mean "no change" rather
+        than "clear".
+        """
+        d = Document(myfile='something.txt')
+        self.assertEqual(d.myfile, 'something.txt')
+        field = d._meta.get_field('myfile')
+        field.save_form_data(d, None)
+        self.assertEqual(d.myfile, 'something.txt')
+
+    def test_changed(self):
+        """
+        FileField.save_form_data(), if passed a truthy value, updates its
+        instance attribute.
+        """
+        d = Document(myfile='something.txt')
+        self.assertEqual(d.myfile, 'something.txt')
+        field = d._meta.get_field('myfile')
+        field.save_form_data(d, 'else.txt')
+        self.assertEqual(d.myfile, 'else.txt')
+
+    def test_delete_when_file_unset(self):
+        """
+        Calling delete on an unset FileField should not call the file deletion
+        process, but fail silently (#20660).
+        """
+        d = Document()
+        d.myfile.delete()
+
+    def test_refresh_from_db(self):
+        d = Document.objects.create(myfile='something.txt')
+        d.refresh_from_db()
+        self.assertIs(d.myfile.instance, d)

+ 34 - 0
tests/model_fields/test_floatfield.py

@@ -0,0 +1,34 @@
+from django.db import transaction
+from django.test import TestCase
+
+from .models import FloatModel
+
+
+class TestFloatField(TestCase):
+
+    def test_float_validates_object(self):
+        instance = FloatModel(size=2.5)
+        # Try setting float field to unsaved object
+        instance.size = instance
+        with transaction.atomic():
+            with self.assertRaises(TypeError):
+                instance.save()
+        # Set value to valid and save
+        instance.size = 2.5
+        instance.save()
+        self.assertTrue(instance.id)
+        # Set field to object on saved instance
+        instance.size = instance
+        msg = (
+            'Tried to update field model_fields.FloatModel.size with a model '
+            'instance, <FloatModel: FloatModel object>. Use a value '
+            'compatible with FloatField.'
+        )
+        with transaction.atomic():
+            with self.assertRaisesMessage(TypeError, msg):
+                instance.save()
+        # Try setting field to object on retrieved object
+        obj = FloatModel.objects.get(pk=instance.id)
+        obj.size = obj
+        with self.assertRaises(TypeError):
+            obj.save()

+ 96 - 0
tests/model_fields/test_foreignkey.py

@@ -0,0 +1,96 @@
+from decimal import Decimal
+
+from django.apps import apps
+from django.core import checks
+from django.db import models
+from django.test import TestCase, skipIfDBFeature
+from django.test.utils import isolate_apps
+from django.utils import six
+
+from .models import Bar, FkToChar, Foo, PrimaryKeyCharModel
+
+
+class ForeignKeyTests(TestCase):
+
+    def test_callable_default(self):
+        """A lazy callable may be used for ForeignKey.default."""
+        a = Foo.objects.create(id=1, a='abc', d=Decimal('12.34'))
+        b = Bar.objects.create(b='bcd')
+        self.assertEqual(b.a, a)
+
+    @skipIfDBFeature('interprets_empty_strings_as_nulls')
+    def test_empty_string_fk(self):
+        """
+        Empty strings foreign key values don't get converted to None (#19299).
+        """
+        char_model_empty = PrimaryKeyCharModel.objects.create(string='')
+        fk_model_empty = FkToChar.objects.create(out=char_model_empty)
+        fk_model_empty = FkToChar.objects.select_related('out').get(id=fk_model_empty.pk)
+        self.assertEqual(fk_model_empty.out, char_model_empty)
+
+    @isolate_apps('model_fields')
+    def test_warning_when_unique_true_on_fk(self):
+        class Foo(models.Model):
+            pass
+
+        class FKUniqueTrue(models.Model):
+            fk_field = models.ForeignKey(Foo, models.CASCADE, unique=True)
+
+        model = FKUniqueTrue()
+        expected_warnings = [
+            checks.Warning(
+                'Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.',
+                hint='ForeignKey(unique=True) is usually better served by a OneToOneField.',
+                obj=FKUniqueTrue.fk_field.field,
+                id='fields.W342',
+            )
+        ]
+        warnings = model.check()
+        self.assertEqual(warnings, expected_warnings)
+
+    def test_related_name_converted_to_text(self):
+        rel_name = Bar._meta.get_field('a').remote_field.related_name
+        self.assertIsInstance(rel_name, six.text_type)
+
+    def test_abstract_model_pending_operations(self):
+        """
+        Foreign key fields declared on abstract models should not add lazy
+        relations to resolve relationship declared as string (#24215).
+        """
+        pending_ops_before = list(apps._pending_operations.items())
+
+        class AbstractForeignKeyModel(models.Model):
+            fk = models.ForeignKey('missing.FK', models.CASCADE)
+
+            class Meta:
+                abstract = True
+
+        self.assertIs(AbstractForeignKeyModel._meta.apps, apps)
+        self.assertEqual(
+            pending_ops_before,
+            list(apps._pending_operations.items()),
+            'Pending lookup added for a foreign key on an abstract model'
+        )
+
+    @isolate_apps('model_fields', 'model_fields.tests')
+    def test_abstract_model_app_relative_foreign_key(self):
+        class AbstractReferent(models.Model):
+            reference = models.ForeignKey('Refered', on_delete=models.CASCADE)
+
+            class Meta:
+                app_label = 'model_fields'
+                abstract = True
+
+        def assert_app_model_resolved(label):
+            class Refered(models.Model):
+                class Meta:
+                    app_label = label
+
+            class ConcreteReferent(AbstractReferent):
+                class Meta:
+                    app_label = label
+
+            self.assertEqual(ConcreteReferent._meta.get_field('reference').related_model, Refered)
+
+        assert_app_model_resolved('model_fields')
+        assert_app_model_resolved('tests')

+ 35 - 0
tests/model_fields/test_genericipaddressfield.py

@@ -0,0 +1,35 @@
+from django.core.exceptions import ValidationError
+from django.db import models
+from django.test import TestCase
+
+from .models import GenericIPAddress
+
+
+class GenericIPAddressFieldTests(TestCase):
+
+    def test_genericipaddressfield_formfield_protocol(self):
+        """
+        GenericIPAddressField with a specified protocol does not generate a
+        formfield without a protocol.
+        """
+        model_field = models.GenericIPAddressField(protocol='IPv4')
+        form_field = model_field.formfield()
+        with self.assertRaises(ValidationError):
+            form_field.clean('::1')
+        model_field = models.GenericIPAddressField(protocol='IPv6')
+        form_field = model_field.formfield()
+        with self.assertRaises(ValidationError):
+            form_field.clean('127.0.0.1')
+
+    def test_null_value(self):
+        """
+        Null values should be resolved to None.
+        """
+        GenericIPAddress.objects.create()
+        o = GenericIPAddress.objects.get()
+        self.assertIsNone(o.ip)
+
+    def test_save_load(self):
+        instance = GenericIPAddress.objects.create(ip='::1')
+        loaded = GenericIPAddress.objects.get()
+        self.assertEqual(loaded.ip, instance.ip)

+ 161 - 0
tests/model_fields/test_integerfield.py

@@ -0,0 +1,161 @@
+from django.core import validators
+from django.core.exceptions import ValidationError
+from django.db import connection, models
+from django.test import SimpleTestCase, TestCase
+from django.utils import six
+
+from .models import (
+    BigIntegerModel, IntegerModel, PositiveIntegerModel,
+    PositiveSmallIntegerModel, SmallIntegerModel,
+)
+
+
+class IntegerFieldTests(TestCase):
+    model = IntegerModel
+    documented_range = (-2147483648, 2147483647)
+
+    @property
+    def backend_range(self):
+        field = self.model._meta.get_field('value')
+        internal_type = field.get_internal_type()
+        return connection.ops.integer_field_range(internal_type)
+
+    def test_documented_range(self):
+        """
+        Values within the documented safe range pass validation, and can be
+        saved and retrieved without corruption.
+        """
+        min_value, max_value = self.documented_range
+
+        instance = self.model(value=min_value)
+        instance.full_clean()
+        instance.save()
+        qs = self.model.objects.filter(value__lte=min_value)
+        self.assertEqual(qs.count(), 1)
+        self.assertEqual(qs[0].value, min_value)
+
+        instance = self.model(value=max_value)
+        instance.full_clean()
+        instance.save()
+        qs = self.model.objects.filter(value__gte=max_value)
+        self.assertEqual(qs.count(), 1)
+        self.assertEqual(qs[0].value, max_value)
+
+    def test_backend_range_save(self):
+        """
+        Backend specific ranges can be saved without corruption.
+        """
+        min_value, max_value = self.backend_range
+
+        if min_value is not None:
+            instance = self.model(value=min_value)
+            instance.full_clean()
+            instance.save()
+            qs = self.model.objects.filter(value__lte=min_value)
+            self.assertEqual(qs.count(), 1)
+            self.assertEqual(qs[0].value, min_value)
+
+        if max_value is not None:
+            instance = self.model(value=max_value)
+            instance.full_clean()
+            instance.save()
+            qs = self.model.objects.filter(value__gte=max_value)
+            self.assertEqual(qs.count(), 1)
+            self.assertEqual(qs[0].value, max_value)
+
+    def test_backend_range_validation(self):
+        """
+        Backend specific ranges are enforced at the model validation level
+        (#12030).
+        """
+        min_value, max_value = self.backend_range
+
+        if min_value is not None:
+            instance = self.model(value=min_value - 1)
+            expected_message = validators.MinValueValidator.message % {
+                'limit_value': min_value,
+            }
+            with self.assertRaisesMessage(ValidationError, expected_message):
+                instance.full_clean()
+            instance.value = min_value
+            instance.full_clean()
+
+        if max_value is not None:
+            instance = self.model(value=max_value + 1)
+            expected_message = validators.MaxValueValidator.message % {
+                'limit_value': max_value,
+            }
+            with self.assertRaisesMessage(ValidationError, expected_message):
+                instance.full_clean()
+            instance.value = max_value
+            instance.full_clean()
+
+    def test_types(self):
+        instance = self.model(value=0)
+        self.assertIsInstance(instance.value, six.integer_types)
+        instance.save()
+        self.assertIsInstance(instance.value, six.integer_types)
+        instance = self.model.objects.get()
+        self.assertIsInstance(instance.value, six.integer_types)
+
+    def test_coercing(self):
+        self.model.objects.create(value='10')
+        instance = self.model.objects.get(value='10')
+        self.assertEqual(instance.value, 10)
+
+
+class SmallIntegerFieldTests(IntegerFieldTests):
+    model = SmallIntegerModel
+    documented_range = (-32768, 32767)
+
+
+class BigIntegerFieldTests(IntegerFieldTests):
+    model = BigIntegerModel
+    documented_range = (-9223372036854775808, 9223372036854775807)
+
+
+class PositiveSmallIntegerFieldTests(IntegerFieldTests):
+    model = PositiveSmallIntegerModel
+    documented_range = (0, 32767)
+
+
+class PositiveIntegerFieldTests(IntegerFieldTests):
+    model = PositiveIntegerModel
+    documented_range = (0, 2147483647)
+
+
+class ValidationTests(SimpleTestCase):
+
+    def test_integerfield_cleans_valid_string(self):
+        f = models.IntegerField()
+        self.assertEqual(f.clean('2', None), 2)
+
+    def test_integerfield_raises_error_on_invalid_intput(self):
+        f = models.IntegerField()
+        with self.assertRaises(ValidationError):
+            f.clean('a', None)
+
+    def test_choices_validation_supports_named_groups(self):
+        f = models.IntegerField(choices=(('group', ((10, 'A'), (20, 'B'))), (30, 'C')))
+        self.assertEqual(10, f.clean(10, None))
+
+    def test_nullable_integerfield_raises_error_with_blank_false(self):
+        f = models.IntegerField(null=True, blank=False)
+        with self.assertRaises(ValidationError):
+            f.clean(None, None)
+
+    def test_nullable_integerfield_cleans_none_on_null_and_blank_true(self):
+        f = models.IntegerField(null=True, blank=True)
+        self.assertIsNone(f.clean(None, None))
+
+    def test_integerfield_raises_error_on_empty_input(self):
+        f = models.IntegerField(null=False)
+        with self.assertRaises(ValidationError):
+            f.clean(None, None)
+        with self.assertRaises(ValidationError):
+            f.clean('', None)
+
+    def test_integerfield_validates_zero_against_choices(self):
+        f = models.IntegerField(choices=((1, 1),))
+        with self.assertRaises(ValidationError):
+            f.clean('0', None)

+ 58 - 0
tests/model_fields/test_manytomanyfield.py

@@ -0,0 +1,58 @@
+from django.apps import apps
+from django.db import models
+from django.test import SimpleTestCase
+from django.test.utils import isolate_apps
+
+
+class ManyToManyFieldTests(SimpleTestCase):
+
+    def test_abstract_model_pending_operations(self):
+        """
+        Many-to-many fields declared on abstract models should not add lazy
+        relations to resolve relationship declared as string (#24215).
+        """
+        pending_ops_before = list(apps._pending_operations.items())
+
+        class AbstractManyToManyModel(models.Model):
+            fk = models.ForeignKey('missing.FK', models.CASCADE)
+
+            class Meta:
+                abstract = True
+
+        self.assertIs(AbstractManyToManyModel._meta.apps, apps)
+        self.assertEqual(
+            pending_ops_before,
+            list(apps._pending_operations.items()),
+            'Pending lookup added for a many-to-many field on an abstract model'
+        )
+
+    @isolate_apps('model_fields', 'model_fields.tests')
+    def test_abstract_model_app_relative_foreign_key(self):
+        class AbstractReferent(models.Model):
+            reference = models.ManyToManyField('Refered', through='Through')
+
+            class Meta:
+                app_label = 'model_fields'
+                abstract = True
+
+        def assert_app_model_resolved(label):
+            class Refered(models.Model):
+                class Meta:
+                    app_label = label
+
+            class Through(models.Model):
+                refered = models.ForeignKey('Refered', on_delete=models.CASCADE)
+                referent = models.ForeignKey('ConcreteReferent', on_delete=models.CASCADE)
+
+                class Meta:
+                    app_label = label
+
+            class ConcreteReferent(AbstractReferent):
+                class Meta:
+                    app_label = label
+
+            self.assertEqual(ConcreteReferent._meta.get_field('reference').related_model, Refered)
+            self.assertEqual(ConcreteReferent.reference.through, Through)
+
+        assert_app_model_resolved('model_fields')
+        assert_app_model_resolved('tests')

+ 138 - 0
tests/model_fields/test_promises.py

@@ -0,0 +1,138 @@
+from __future__ import unicode_literals
+
+import datetime
+import unittest
+from decimal import Decimal
+
+from django.db.models.fields import (
+    AutoField, BigIntegerField, BinaryField, BooleanField, CharField,
+    CommaSeparatedIntegerField, DateField, DateTimeField, DecimalField,
+    EmailField, FilePathField, FloatField, GenericIPAddressField, IntegerField,
+    IPAddressField, NullBooleanField, PositiveIntegerField,
+    PositiveSmallIntegerField, SlugField, SmallIntegerField, TextField,
+    TimeField, URLField,
+)
+from django.db.models.fields.files import FileField, ImageField
+from django.test import SimpleTestCase
+from django.utils import six
+from django.utils.functional import lazy
+
+
+class PromiseTest(SimpleTestCase):
+
+    def test_AutoField(self):
+        lazy_func = lazy(lambda: 1, int)
+        self.assertIsInstance(AutoField(primary_key=True).get_prep_value(lazy_func()), int)
+
+    @unittest.skipIf(six.PY3, 'Python 3 has no `long` type.')
+    def test_BigIntegerField(self):
+        lazy_func = lazy(lambda: long(9999999999999999999), long)  # NOQA: long undefined on PY3
+        self.assertIsInstance(BigIntegerField().get_prep_value(lazy_func()), long)  # NOQA
+
+    def test_BinaryField(self):
+        lazy_func = lazy(lambda: b'', bytes)
+        self.assertIsInstance(BinaryField().get_prep_value(lazy_func()), bytes)
+
+    def test_BooleanField(self):
+        lazy_func = lazy(lambda: True, bool)
+        self.assertIsInstance(BooleanField().get_prep_value(lazy_func()), bool)
+
+    def test_CharField(self):
+        lazy_func = lazy(lambda: '', six.text_type)
+        self.assertIsInstance(CharField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(CharField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_CommaSeparatedIntegerField(self):
+        lazy_func = lazy(lambda: '1,2', six.text_type)
+        self.assertIsInstance(CommaSeparatedIntegerField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(CommaSeparatedIntegerField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_DateField(self):
+        lazy_func = lazy(lambda: datetime.date.today(), datetime.date)
+        self.assertIsInstance(DateField().get_prep_value(lazy_func()), datetime.date)
+
+    def test_DateTimeField(self):
+        lazy_func = lazy(lambda: datetime.datetime.now(), datetime.datetime)
+        self.assertIsInstance(DateTimeField().get_prep_value(lazy_func()), datetime.datetime)
+
+    def test_DecimalField(self):
+        lazy_func = lazy(lambda: Decimal('1.2'), Decimal)
+        self.assertIsInstance(DecimalField().get_prep_value(lazy_func()), Decimal)
+
+    def test_EmailField(self):
+        lazy_func = lazy(lambda: 'mailbox@domain.com', six.text_type)
+        self.assertIsInstance(EmailField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_FileField(self):
+        lazy_func = lazy(lambda: 'filename.ext', six.text_type)
+        self.assertIsInstance(FileField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(FileField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_FilePathField(self):
+        lazy_func = lazy(lambda: 'tests.py', six.text_type)
+        self.assertIsInstance(FilePathField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(FilePathField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_FloatField(self):
+        lazy_func = lazy(lambda: 1.2, float)
+        self.assertIsInstance(FloatField().get_prep_value(lazy_func()), float)
+
+    def test_ImageField(self):
+        lazy_func = lazy(lambda: 'filename.ext', six.text_type)
+        self.assertIsInstance(ImageField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_IntegerField(self):
+        lazy_func = lazy(lambda: 1, int)
+        self.assertIsInstance(IntegerField().get_prep_value(lazy_func()), int)
+
+    def test_IPAddressField(self):
+        lazy_func = lazy(lambda: '127.0.0.1', six.text_type)
+        self.assertIsInstance(IPAddressField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(IPAddressField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_GenericIPAddressField(self):
+        lazy_func = lazy(lambda: '127.0.0.1', six.text_type)
+        self.assertIsInstance(GenericIPAddressField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(GenericIPAddressField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_NullBooleanField(self):
+        lazy_func = lazy(lambda: True, bool)
+        self.assertIsInstance(NullBooleanField().get_prep_value(lazy_func()), bool)
+
+    def test_PositiveIntegerField(self):
+        lazy_func = lazy(lambda: 1, int)
+        self.assertIsInstance(PositiveIntegerField().get_prep_value(lazy_func()), int)
+
+    def test_PositiveSmallIntegerField(self):
+        lazy_func = lazy(lambda: 1, int)
+        self.assertIsInstance(PositiveSmallIntegerField().get_prep_value(lazy_func()), int)
+
+    def test_SlugField(self):
+        lazy_func = lazy(lambda: 'slug', six.text_type)
+        self.assertIsInstance(SlugField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(SlugField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_SmallIntegerField(self):
+        lazy_func = lazy(lambda: 1, int)
+        self.assertIsInstance(SmallIntegerField().get_prep_value(lazy_func()), int)
+
+    def test_TextField(self):
+        lazy_func = lazy(lambda: 'Abc', six.text_type)
+        self.assertIsInstance(TextField().get_prep_value(lazy_func()), six.text_type)
+        lazy_func = lazy(lambda: 0, int)
+        self.assertIsInstance(TextField().get_prep_value(lazy_func()), six.text_type)
+
+    def test_TimeField(self):
+        lazy_func = lazy(lambda: datetime.datetime.now().time(), datetime.time)
+        self.assertIsInstance(TimeField().get_prep_value(lazy_func()), datetime.time)
+
+    def test_URLField(self):
+        lazy_func = lazy(lambda: 'http://domain.com', six.text_type)
+        self.assertIsInstance(URLField().get_prep_value(lazy_func()), six.text_type)

+ 25 - 0
tests/model_fields/test_slugfield.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.test import TestCase
+
+from .models import BigS, UnicodeSlugField
+
+
+class SlugFieldTests(TestCase):
+
+    def test_slugfield_max_length(self):
+        """
+        SlugField honors max_length.
+        """
+        bs = BigS.objects.create(s='slug' * 50)
+        bs = BigS.objects.get(pk=bs.pk)
+        self.assertEqual(bs.s, 'slug' * 50)
+
+    def test_slugfield_unicode_max_length(self):
+        """
+        SlugField with allow_unicode=True honors max_length.
+        """
+        bs = UnicodeSlugField.objects.create(s='你好你好' * 50)
+        bs = UnicodeSlugField.objects.get(pk=bs.pk)
+        self.assertEqual(bs.s, '你好你好' * 50)

+ 25 - 0
tests/model_fields/test_textfield.py

@@ -0,0 +1,25 @@
+from django.db import models
+from django.test import TestCase
+
+from .models import Post
+
+
+class TextFieldTests(TestCase):
+
+    def test_max_length_passed_to_formfield(self):
+        """
+        TextField passes its max_length attribute to form fields created using
+        their formfield() method.
+        """
+        tf1 = models.TextField()
+        tf2 = models.TextField(max_length=2345)
+        self.assertIsNone(tf1.formfield().max_length)
+        self.assertEqual(2345, tf2.formfield().max_length)
+
+    def test_to_python(self):
+        """TextField.to_python() should return a string."""
+        f = models.TextField()
+        self.assertEqual(f.to_python(1), '1')
+
+    def test_lookup_integer_in_textfield(self):
+        self.assertEqual(Post.objects.filter(body=24).count(), 0)

+ 19 - 1054
tests/model_fields/tests.py

@@ -1,44 +1,19 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import datetime
-import unittest
-from decimal import Decimal
-
-from django import forms, test
-from django.apps import apps
-from django.core import checks, validators
-from django.core.exceptions import ValidationError
-from django.db import IntegrityError, connection, models, transaction
-from django.db.models.fields import (
-    NOT_PROVIDED, AutoField, BigIntegerField, BinaryField, BooleanField,
-    CharField, CommaSeparatedIntegerField, DateField, DateTimeField,
-    DecimalField, EmailField, FilePathField, FloatField, GenericIPAddressField,
-    IntegerField, IPAddressField, NullBooleanField, PositiveIntegerField,
-    PositiveSmallIntegerField, SlugField, SmallIntegerField, TextField,
-    TimeField, URLField,
-)
-from django.db.models.fields.files import FileField, ImageField
-from django.test.utils import isolate_apps, requires_tz_support
-from django.utils import six, timezone
+from django import forms
+from django.db import models
+from django.test import SimpleTestCase, TestCase
 from django.utils.encoding import force_str
-from django.utils.functional import lazy
 
 from .models import (
-    Bar, BigD, BigIntegerModel, BigS, BooleanModel, DataModel, DateTimeModel,
-    Document, FksToBooleans, FkToChar, FloatModel, Foo, GenericIPAddress,
-    IntegerModel, NullBooleanModel, PositiveIntegerModel,
-    PositiveSmallIntegerModel, Post, PrimaryKeyCharModel, RenamedField,
-    SmallIntegerModel, UnicodeSlugField, VerboseNameField, Whiz, WhizIter,
-    WhizIterEmpty,
+    Foo, RenamedField, VerboseNameField, Whiz, WhizIter, WhizIterEmpty,
 )
 
 
-class BasicFieldTests(test.TestCase):
+class BasicFieldTests(TestCase):
+
     def test_show_hidden_initial(self):
         """
-        Regression test for #12913. Make sure fields with choices respect
-        show_hidden_initial as a kwarg to models.Field.formfield()
+        Fields with choices respect show_hidden_initial as a kwarg to
+        formfield().
         """
         choices = [(0, 0), (1, 1)]
         model_field = models.Field(choices=choices)
@@ -48,20 +23,9 @@ class BasicFieldTests(test.TestCase):
         form_field = model_field.formfield(show_hidden_initial=False)
         self.assertFalse(form_field.show_hidden_initial)
 
-    def test_nullbooleanfield_blank(self):
-        """
-        Regression test for #13071: NullBooleanField should not throw
-        a validation error when given a value of None.
-        """
-        nullboolean = NullBooleanModel(nbfield=None)
-        try:
-            nullboolean.full_clean()
-        except ValidationError as e:
-            self.fail("NullBooleanField failed validation with value of None: %s" % e.messages)
-
     def test_field_repr(self):
         """
-        Regression test for #5931: __repr__ of a field also displays its name
+        __repr__() of a field displays its name.
         """
         f = Foo._meta.get_field('a')
         self.assertEqual(repr(f), '<django.db.models.fields.CharField: a>')
@@ -70,8 +34,8 @@ class BasicFieldTests(test.TestCase):
 
     def test_field_name(self):
         """
-        Regression test for #14695: explicitly defined field name overwritten
-        by model's attribute name.
+        A defined field name (name="fieldname") is used instead of the model
+        model's attribute name (modelname).
         """
         instance = RenamedField()
         self.assertTrue(hasattr(instance, 'get_fieldname_display'))
@@ -80,40 +44,12 @@ class BasicFieldTests(test.TestCase):
     def test_field_verbose_name(self):
         m = VerboseNameField
         for i in range(1, 24):
-            self.assertEqual(m._meta.get_field('field%d' % i).verbose_name,
-                             'verbose field%d' % i)
+            self.assertEqual(m._meta.get_field('field%d' % i).verbose_name, 'verbose field%d' % i)
 
         self.assertEqual(m._meta.get_field('id').verbose_name, 'verbose pk')
 
-    def test_float_validates_object(self):
-        instance = FloatModel(size=2.5)
-        # Try setting float field to unsaved object
-        instance.size = instance
-        with transaction.atomic():
-            with self.assertRaises(TypeError):
-                instance.save()
-        # Set value to valid and save
-        instance.size = 2.5
-        instance.save()
-        self.assertTrue(instance.id)
-        # Set field to object on saved instance
-        instance.size = instance
-        msg = (
-            "Tried to update field model_fields.FloatModel.size with a model "
-            "instance, <FloatModel: FloatModel object>. Use a value "
-            "compatible with FloatField."
-        )
-        with transaction.atomic():
-            with self.assertRaisesMessage(TypeError, msg):
-                instance.save()
-        # Try setting field to object on retrieved object
-        obj = FloatModel.objects.get(pk=instance.id)
-        obj.size = obj
-        with self.assertRaises(TypeError):
-            obj.save()
-
     def test_choices_form_class(self):
-        """Can supply a custom choices form class. Regression for #20999."""
+        """Can supply a custom choices form class to Field.formfield()"""
         choices = [('a', 'a')]
         field = models.CharField(choices=choices)
         klass = forms.TypedMultipleChoiceField
@@ -121,448 +57,15 @@ class BasicFieldTests(test.TestCase):
 
     def test_field_str(self):
         f = Foo._meta.get_field('a')
-        self.assertEqual(force_str(f), "model_fields.Foo.a")
-
-
-class DecimalFieldTests(test.TestCase):
-    def test_to_python(self):
-        f = models.DecimalField(max_digits=4, decimal_places=2)
-        self.assertEqual(f.to_python(3), Decimal("3"))
-        self.assertEqual(f.to_python("3.14"), Decimal("3.14"))
-        with self.assertRaises(ValidationError):
-            f.to_python("abc")
-
-    def test_default(self):
-        f = models.DecimalField(default=Decimal("0.00"))
-        self.assertEqual(f.get_default(), Decimal("0.00"))
-
-    def test_format(self):
-        f = models.DecimalField(max_digits=5, decimal_places=1)
-        self.assertEqual(f._format(f.to_python(2)), '2.0')
-        self.assertEqual(f._format(f.to_python('2.6')), '2.6')
-        self.assertEqual(f._format(None), None)
-
-    def test_get_db_prep_lookup(self):
-        f = models.DecimalField(max_digits=5, decimal_places=1)
-        self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
-
-    def test_filter_with_strings(self):
-        """
-        We should be able to filter decimal fields using strings (#8023)
-        """
-        Foo.objects.create(id=1, a='abc', d=Decimal("12.34"))
-        self.assertEqual(list(Foo.objects.filter(d='1.23')), [])
-
-    def test_save_without_float_conversion(self):
-        """
-        Ensure decimals don't go through a corrupting float conversion during
-        save (#5079).
-        """
-        bd = BigD(d="12.9")
-        bd.save()
-        bd = BigD.objects.get(pk=bd.pk)
-        self.assertEqual(bd.d, Decimal("12.9"))
-
-    def test_lookup_really_big_value(self):
-        """
-        Ensure that really big values can be used in a filter statement, even
-        with older Python versions.
-        """
-        # This should not crash. That counts as a win for our purposes.
-        Foo.objects.filter(d__gte=100000000000)
-
-    def test_max_digits_validation(self):
-        field = models.DecimalField(max_digits=2)
-        expected_message = validators.DecimalValidator.messages['max_digits'] % {'max': 2}
-        with self.assertRaisesMessage(ValidationError, expected_message):
-            field.clean(100, None)
-
-    def test_max_decimal_places_validation(self):
-        field = models.DecimalField(decimal_places=1)
-        expected_message = validators.DecimalValidator.messages['max_decimal_places'] % {'max': 1}
-        with self.assertRaisesMessage(ValidationError, expected_message):
-            field.clean(Decimal('0.99'), None)
-
-    def test_max_whole_digits_validation(self):
-        field = models.DecimalField(max_digits=3, decimal_places=1)
-        expected_message = validators.DecimalValidator.messages['max_whole_digits'] % {'max': 2}
-        with self.assertRaisesMessage(ValidationError, expected_message):
-            field.clean(Decimal('999'), None)
-
-
-class ForeignKeyTests(test.TestCase):
-    def test_callable_default(self):
-        """Test the use of a lazy callable for ForeignKey.default"""
-        a = Foo.objects.create(id=1, a='abc', d=Decimal("12.34"))
-        b = Bar.objects.create(b="bcd")
-        self.assertEqual(b.a, a)
-
-    @test.skipIfDBFeature('interprets_empty_strings_as_nulls')
-    def test_empty_string_fk(self):
-        """
-        Test that foreign key values to empty strings don't get converted
-        to None (#19299)
-        """
-        char_model_empty = PrimaryKeyCharModel.objects.create(string='')
-        fk_model_empty = FkToChar.objects.create(out=char_model_empty)
-        fk_model_empty = FkToChar.objects.select_related('out').get(id=fk_model_empty.pk)
-        self.assertEqual(fk_model_empty.out, char_model_empty)
-
-    @isolate_apps('model_fields')
-    def test_warning_when_unique_true_on_fk(self):
-        class Foo(models.Model):
-            pass
-
-        class FKUniqueTrue(models.Model):
-            fk_field = models.ForeignKey(Foo, models.CASCADE, unique=True)
-
-        model = FKUniqueTrue()
-        expected_warnings = [
-            checks.Warning(
-                'Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.',
-                hint='ForeignKey(unique=True) is usually better served by a OneToOneField.',
-                obj=FKUniqueTrue.fk_field.field,
-                id='fields.W342',
-            )
-        ]
-        warnings = model.check()
-        self.assertEqual(warnings, expected_warnings)
-
-    def test_related_name_converted_to_text(self):
-        rel_name = Bar._meta.get_field('a').remote_field.related_name
-        self.assertIsInstance(rel_name, six.text_type)
-
-    def test_abstract_model_pending_operations(self):
-        """
-        Foreign key fields declared on abstract models should not add lazy relations to
-        resolve relationship declared as string. refs #24215
-        """
-        pending_ops_before = list(apps._pending_operations.items())
-
-        class AbstractForeignKeyModel(models.Model):
-            fk = models.ForeignKey('missing.FK', models.CASCADE)
-
-            class Meta:
-                abstract = True
-
-        self.assertIs(AbstractForeignKeyModel._meta.apps, apps)
-        self.assertEqual(
-            pending_ops_before,
-            list(apps._pending_operations.items()),
-            "Pending lookup added for a foreign key on an abstract model"
-        )
-
-    @isolate_apps('model_fields', 'model_fields.tests')
-    def test_abstract_model_app_relative_foreign_key(self):
-        class AbstractReferent(models.Model):
-            reference = models.ForeignKey('Refered', on_delete=models.CASCADE)
-
-            class Meta:
-                app_label = 'model_fields'
-                abstract = True
-
-        def assert_app_model_resolved(label):
-            class Refered(models.Model):
-                class Meta:
-                    app_label = label
-
-            class ConcreteReferent(AbstractReferent):
-                class Meta:
-                    app_label = label
-
-            self.assertEqual(ConcreteReferent._meta.get_field('reference').related_model, Refered)
-
-        assert_app_model_resolved('model_fields')
-        assert_app_model_resolved('tests')
-
-
-class ManyToManyFieldTests(test.SimpleTestCase):
-    def test_abstract_model_pending_operations(self):
-        """
-        Many-to-many fields declared on abstract models should not add lazy relations to
-        resolve relationship declared as string. refs #24215
-        """
-        pending_ops_before = list(apps._pending_operations.items())
-
-        class AbstractManyToManyModel(models.Model):
-            fk = models.ForeignKey('missing.FK', models.CASCADE)
-
-            class Meta:
-                abstract = True
-
-        self.assertIs(AbstractManyToManyModel._meta.apps, apps)
-        self.assertEqual(
-            pending_ops_before,
-            list(apps._pending_operations.items()),
-            "Pending lookup added for a many-to-many field on an abstract model"
-        )
+        self.assertEqual(force_str(f), 'model_fields.Foo.a')
 
-    @isolate_apps('model_fields', 'model_fields.tests')
-    def test_abstract_model_app_relative_foreign_key(self):
-        class AbstractReferent(models.Model):
-            reference = models.ManyToManyField('Refered', through='Through')
 
-            class Meta:
-                app_label = 'model_fields'
-                abstract = True
+class ChoicesTests(SimpleTestCase):
 
-        def assert_app_model_resolved(label):
-            class Refered(models.Model):
-                class Meta:
-                    app_label = label
-
-            class Through(models.Model):
-                refered = models.ForeignKey('Refered', on_delete=models.CASCADE)
-                referent = models.ForeignKey('ConcreteReferent', on_delete=models.CASCADE)
-
-                class Meta:
-                    app_label = label
-
-            class ConcreteReferent(AbstractReferent):
-                class Meta:
-                    app_label = label
-
-            self.assertEqual(ConcreteReferent._meta.get_field('reference').related_model, Refered)
-            self.assertEqual(ConcreteReferent.reference.through, Through)
-
-        assert_app_model_resolved('model_fields')
-        assert_app_model_resolved('tests')
-
-
-class TextFieldTests(test.TestCase):
-    def test_to_python(self):
-        """TextField.to_python() should return a string"""
-        f = models.TextField()
-        self.assertEqual(f.to_python(1), '1')
-
-
-class DateTimeFieldTests(test.TestCase):
-    def test_datetimefield_to_python_usecs(self):
-        """DateTimeField.to_python should support usecs"""
-        f = models.DateTimeField()
-        self.assertEqual(f.to_python('2001-01-02 03:04:05.000006'),
-                         datetime.datetime(2001, 1, 2, 3, 4, 5, 6))
-        self.assertEqual(f.to_python('2001-01-02 03:04:05.999999'),
-                         datetime.datetime(2001, 1, 2, 3, 4, 5, 999999))
-
-    def test_timefield_to_python_usecs(self):
-        """TimeField.to_python should support usecs"""
-        f = models.TimeField()
-        self.assertEqual(f.to_python('01:02:03.000004'),
-                         datetime.time(1, 2, 3, 4))
-        self.assertEqual(f.to_python('01:02:03.999999'),
-                         datetime.time(1, 2, 3, 999999))
-
-    @test.skipUnlessDBFeature("supports_microsecond_precision")
-    def test_datetimes_save_completely(self):
-        dat = datetime.date(2014, 3, 12)
-        datetim = datetime.datetime(2014, 3, 12, 21, 22, 23, 240000)
-        tim = datetime.time(21, 22, 23, 240000)
-        DateTimeModel.objects.create(d=dat, dt=datetim, t=tim)
-        obj = DateTimeModel.objects.first()
-        self.assertTrue(obj)
-        self.assertEqual(obj.d, dat)
-        self.assertEqual(obj.dt, datetim)
-        self.assertEqual(obj.t, tim)
-
-    @test.override_settings(USE_TZ=False)
-    def test_lookup_date_without_use_tz(self):
-        d = datetime.date(2014, 3, 12)
-        dt1 = datetime.datetime(2014, 3, 12, 21, 22, 23, 240000)
-        dt2 = datetime.datetime(2014, 3, 11, 21, 22, 23, 240000)
-        t = datetime.time(21, 22, 23, 240000)
-        m = DateTimeModel.objects.create(d=d, dt=dt1, t=t)
-        # Other model with different datetime.
-        DateTimeModel.objects.create(d=d, dt=dt2, t=t)
-        self.assertEqual(m, DateTimeModel.objects.get(dt__date=d))
-
-    @requires_tz_support
-    @test.skipUnlessDBFeature('has_zoneinfo_database')
-    @test.override_settings(USE_TZ=True, TIME_ZONE='America/Vancouver')
-    def test_lookup_date_with_use_tz(self):
-        d = datetime.date(2014, 3, 12)
-        # The following is equivalent to UTC 2014-03-12 18:34:23.24000.
-        dt1 = datetime.datetime(
-            2014, 3, 12, 10, 22, 23, 240000,
-            tzinfo=timezone.get_current_timezone()
-        )
-        # The following is equivalent to UTC 2014-03-13 05:34:23.24000.
-        dt2 = datetime.datetime(
-            2014, 3, 12, 21, 22, 23, 240000,
-            tzinfo=timezone.get_current_timezone()
-        )
-        t = datetime.time(21, 22, 23, 240000)
-        m1 = DateTimeModel.objects.create(d=d, dt=dt1, t=t)
-        m2 = DateTimeModel.objects.create(d=d, dt=dt2, t=t)
-        # In Vancouver, we expect both results.
-        self.assertQuerysetEqual(
-            DateTimeModel.objects.filter(dt__date=d),
-            [repr(m1), repr(m2)],
-            ordered=False
-        )
-        with self.settings(TIME_ZONE='UTC'):
-            # But in UTC, the __date only matches one of them.
-            self.assertQuerysetEqual(
-                DateTimeModel.objects.filter(dt__date=d),
-                [repr(m1)]
-            )
-
-
-class BooleanFieldTests(test.TestCase):
-    def _test_get_db_prep_lookup(self, f):
-        self.assertEqual(f.get_db_prep_lookup('exact', True, connection=connection), [True])
-        self.assertEqual(f.get_db_prep_lookup('exact', '1', connection=connection), [True])
-        self.assertEqual(f.get_db_prep_lookup('exact', 1, connection=connection), [True])
-        self.assertEqual(f.get_db_prep_lookup('exact', False, connection=connection), [False])
-        self.assertEqual(f.get_db_prep_lookup('exact', '0', connection=connection), [False])
-        self.assertEqual(f.get_db_prep_lookup('exact', 0, connection=connection), [False])
-        self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
-
-    def _test_to_python(self, f):
-        self.assertIs(f.to_python(1), True)
-        self.assertIs(f.to_python(0), False)
-
-    def test_booleanfield_get_db_prep_lookup(self):
-        self._test_get_db_prep_lookup(models.BooleanField())
-
-    def test_nullbooleanfield_get_db_prep_lookup(self):
-        self._test_get_db_prep_lookup(models.NullBooleanField())
-
-    def test_booleanfield_to_python(self):
-        self._test_to_python(models.BooleanField())
-
-    def test_nullbooleanfield_to_python(self):
-        self._test_to_python(models.NullBooleanField())
-
-    def test_charfield_textfield_max_length_passed_to_formfield(self):
-        """
-        Test that CharField and TextField pass their max_length attributes to
-        form fields created using their .formfield() method (#22206).
-        """
-        cf1 = models.CharField()
-        cf2 = models.CharField(max_length=1234)
-        self.assertIsNone(cf1.formfield().max_length)
-        self.assertEqual(1234, cf2.formfield().max_length)
-
-        tf1 = models.TextField()
-        tf2 = models.TextField(max_length=2345)
-        self.assertIsNone(tf1.formfield().max_length)
-        self.assertEqual(2345, tf2.formfield().max_length)
-
-    def test_booleanfield_choices_blank(self):
-        """
-        Test that BooleanField with choices and defaults doesn't generate a
-        formfield with the blank option (#9640, #10549).
-        """
-        choices = [(1, 'Si'), (2, 'No')]
-        f = models.BooleanField(choices=choices, default=1, null=False)
-        self.assertEqual(f.formfield().choices, choices)
-
-    def test_return_type(self):
-        b = BooleanModel()
-        b.bfield = True
-        b.save()
-        b2 = BooleanModel.objects.get(pk=b.pk)
-        self.assertIsInstance(b2.bfield, bool)
-        self.assertEqual(b2.bfield, True)
-
-        b3 = BooleanModel()
-        b3.bfield = False
-        b3.save()
-        b4 = BooleanModel.objects.get(pk=b3.pk)
-        self.assertIsInstance(b4.bfield, bool)
-        self.assertEqual(b4.bfield, False)
-
-        b = NullBooleanModel()
-        b.nbfield = True
-        b.save()
-        b2 = NullBooleanModel.objects.get(pk=b.pk)
-        self.assertIsInstance(b2.nbfield, bool)
-        self.assertEqual(b2.nbfield, True)
-
-        b3 = NullBooleanModel()
-        b3.nbfield = False
-        b3.save()
-        b4 = NullBooleanModel.objects.get(pk=b3.pk)
-        self.assertIsInstance(b4.nbfield, bool)
-        self.assertEqual(b4.nbfield, False)
-
-        # http://code.djangoproject.com/ticket/13293
-        # Verify that when an extra clause exists, the boolean
-        # conversions are applied with an offset
-        b5 = BooleanModel.objects.all().extra(
-            select={'string_col': 'string'})[0]
-        self.assertNotIsInstance(b5.pk, bool)
-
-    def test_select_related(self):
-        """
-        Test type of boolean fields when retrieved via select_related() (MySQL,
-        #15040)
-        """
-        bmt = BooleanModel.objects.create(bfield=True)
-        bmf = BooleanModel.objects.create(bfield=False)
-        nbmt = NullBooleanModel.objects.create(nbfield=True)
-        nbmf = NullBooleanModel.objects.create(nbfield=False)
-
-        m1 = FksToBooleans.objects.create(bf=bmt, nbf=nbmt)
-        m2 = FksToBooleans.objects.create(bf=bmf, nbf=nbmf)
-
-        # Test select_related('fk_field_name')
-        ma = FksToBooleans.objects.select_related('bf').get(pk=m1.id)
-        # verify types -- shouldn't be 0/1
-        self.assertIsInstance(ma.bf.bfield, bool)
-        self.assertIsInstance(ma.nbf.nbfield, bool)
-        # verify values
-        self.assertEqual(ma.bf.bfield, True)
-        self.assertEqual(ma.nbf.nbfield, True)
-
-        # Test select_related()
-        mb = FksToBooleans.objects.select_related().get(pk=m1.id)
-        mc = FksToBooleans.objects.select_related().get(pk=m2.id)
-        # verify types -- shouldn't be 0/1
-        self.assertIsInstance(mb.bf.bfield, bool)
-        self.assertIsInstance(mb.nbf.nbfield, bool)
-        self.assertIsInstance(mc.bf.bfield, bool)
-        self.assertIsInstance(mc.nbf.nbfield, bool)
-        # verify values
-        self.assertEqual(mb.bf.bfield, True)
-        self.assertEqual(mb.nbf.nbfield, True)
-        self.assertEqual(mc.bf.bfield, False)
-        self.assertEqual(mc.nbf.nbfield, False)
-
-    def test_null_default(self):
-        """
-        Check that a BooleanField defaults to None -- which isn't
-        a valid value (#15124).
-        """
-        # Patch the boolean field's default value. We give it a default
-        # value when defining the model to satisfy the check tests
-        # #20895.
-        boolean_field = BooleanModel._meta.get_field('bfield')
-        self.assertTrue(boolean_field.has_default())
-        old_default = boolean_field.default
-        try:
-            boolean_field.default = NOT_PROVIDED
-            # check patch was successful
-            self.assertFalse(boolean_field.has_default())
-            b = BooleanModel()
-            self.assertIsNone(b.bfield)
-            with transaction.atomic():
-                with self.assertRaises(IntegrityError):
-                    b.save()
-        finally:
-            boolean_field.default = old_default
-
-        nb = NullBooleanModel()
-        self.assertIsNone(nb.nbfield)
-        nb.save()           # no error
-
-
-class ChoicesTests(test.SimpleTestCase):
     def test_choices_and_field_display(self):
         """
-        Check that get_choices() interacts with get_FIELD_display() to return
-        the expected values (#7913).
+        get_choices() interacts with get_FIELD_display() to return the expected
+        values.
         """
         self.assertEqual(Whiz(c=1).get_c_display(), 'First')    # A nested value
         self.assertEqual(Whiz(c=0).get_c_display(), 'Other')    # A top level value
@@ -572,7 +75,7 @@ class ChoicesTests(test.SimpleTestCase):
 
     def test_iterator_choices(self):
         """
-        Check that get_choices works with Iterators (#23112).
+        get_choices() works with Iterators.
         """
         self.assertEqual(WhizIter(c=1).c, 1)          # A nested value
         self.assertEqual(WhizIter(c=9).c, 9)          # Invalid value
@@ -581,547 +84,9 @@ class ChoicesTests(test.SimpleTestCase):
 
     def test_empty_iterator_choices(self):
         """
-        Check that get_choices works with empty iterators (#23112).
+        get_choices() works with empty iterators.
         """
         self.assertEqual(WhizIterEmpty(c="a").c, "a")      # A nested value
         self.assertEqual(WhizIterEmpty(c="b").c, "b")      # Invalid value
         self.assertEqual(WhizIterEmpty(c=None).c, None)    # Blank value
         self.assertEqual(WhizIterEmpty(c='').c, '')        # Empty value
-
-
-class SlugFieldTests(test.TestCase):
-    def test_slugfield_max_length(self):
-        """
-        Make sure SlugField honors max_length (#9706)
-        """
-        bs = BigS.objects.create(s='slug' * 50)
-        bs = BigS.objects.get(pk=bs.pk)
-        self.assertEqual(bs.s, 'slug' * 50)
-
-    def test_slugfield_unicode_max_length(self):
-        """
-        SlugField with allow_unicode=True should honor max_length.
-        """
-        bs = UnicodeSlugField.objects.create(s='你好你好' * 50)
-        bs = UnicodeSlugField.objects.get(pk=bs.pk)
-        self.assertEqual(bs.s, '你好你好' * 50)
-
-
-class ValidationTest(test.SimpleTestCase):
-    def test_charfield_raises_error_on_empty_string(self):
-        f = models.CharField()
-        with self.assertRaises(ValidationError):
-            f.clean("", None)
-
-    def test_charfield_cleans_empty_string_when_blank_true(self):
-        f = models.CharField(blank=True)
-        self.assertEqual('', f.clean('', None))
-
-    def test_integerfield_cleans_valid_string(self):
-        f = models.IntegerField()
-        self.assertEqual(2, f.clean('2', None))
-
-    def test_integerfield_raises_error_on_invalid_intput(self):
-        f = models.IntegerField()
-        with self.assertRaises(ValidationError):
-            f.clean("a", None)
-
-    def test_charfield_with_choices_cleans_valid_choice(self):
-        f = models.CharField(max_length=1,
-                             choices=[('a', 'A'), ('b', 'B')])
-        self.assertEqual('a', f.clean('a', None))
-
-    def test_charfield_with_choices_raises_error_on_invalid_choice(self):
-        f = models.CharField(choices=[('a', 'A'), ('b', 'B')])
-        with self.assertRaises(ValidationError):
-            f.clean("not a", None)
-
-    def test_charfield_get_choices_with_blank_defined(self):
-        f = models.CharField(choices=[('', '<><>'), ('a', 'A')])
-        self.assertEqual(f.get_choices(True), [('', '<><>'), ('a', 'A')])
-
-    def test_charfield_get_choices_doesnt_evaluate_lazy_strings(self):
-        # Regression test for #23098
-        # Will raise ZeroDivisionError if lazy is evaluated
-        lazy_func = lazy(lambda x: 0 / 0, int)
-        f = models.CharField(choices=[(lazy_func('group'), (('a', 'A'), ('b', 'B')))])
-        self.assertEqual(f.get_choices(True)[0], ('', '---------'))
-
-    def test_choices_validation_supports_named_groups(self):
-        f = models.IntegerField(
-            choices=(('group', ((10, 'A'), (20, 'B'))), (30, 'C')))
-        self.assertEqual(10, f.clean(10, None))
-
-    def test_nullable_integerfield_raises_error_with_blank_false(self):
-        f = models.IntegerField(null=True, blank=False)
-        with self.assertRaises(ValidationError):
-            f.clean(None, None)
-
-    def test_nullable_integerfield_cleans_none_on_null_and_blank_true(self):
-        f = models.IntegerField(null=True, blank=True)
-        self.assertIsNone(f.clean(None, None))
-
-    def test_integerfield_raises_error_on_empty_input(self):
-        f = models.IntegerField(null=False)
-        with self.assertRaises(ValidationError):
-            f.clean(None, None)
-        with self.assertRaises(ValidationError):
-            f.clean('', None)
-
-    def test_integerfield_validates_zero_against_choices(self):
-        f = models.IntegerField(choices=((1, 1),))
-        with self.assertRaises(ValidationError):
-            f.clean('0', None)
-
-    def test_charfield_raises_error_on_empty_input(self):
-        f = models.CharField(null=False)
-        with self.assertRaises(ValidationError):
-            f.clean(None, None)
-
-    def test_datefield_cleans_date(self):
-        f = models.DateField()
-        self.assertEqual(datetime.date(2008, 10, 10), f.clean('2008-10-10', None))
-
-    def test_boolean_field_doesnt_accept_empty_input(self):
-        f = models.BooleanField()
-        with self.assertRaises(ValidationError):
-            f.clean(None, None)
-
-
-class IntegerFieldTests(test.TestCase):
-    model = IntegerModel
-    documented_range = (-2147483648, 2147483647)
-
-    @property
-    def backend_range(self):
-        field = self.model._meta.get_field('value')
-        internal_type = field.get_internal_type()
-        return connection.ops.integer_field_range(internal_type)
-
-    def test_documented_range(self):
-        """
-        Ensure that values within the documented safe range pass validation,
-        can be saved and retrieved without corruption.
-        """
-        min_value, max_value = self.documented_range
-
-        instance = self.model(value=min_value)
-        instance.full_clean()
-        instance.save()
-        qs = self.model.objects.filter(value__lte=min_value)
-        self.assertEqual(qs.count(), 1)
-        self.assertEqual(qs[0].value, min_value)
-
-        instance = self.model(value=max_value)
-        instance.full_clean()
-        instance.save()
-        qs = self.model.objects.filter(value__gte=max_value)
-        self.assertEqual(qs.count(), 1)
-        self.assertEqual(qs[0].value, max_value)
-
-    def test_backend_range_save(self):
-        """
-        Ensure that backend specific range can be saved without corruption.
-        """
-        min_value, max_value = self.backend_range
-
-        if min_value is not None:
-            instance = self.model(value=min_value)
-            instance.full_clean()
-            instance.save()
-            qs = self.model.objects.filter(value__lte=min_value)
-            self.assertEqual(qs.count(), 1)
-            self.assertEqual(qs[0].value, min_value)
-
-        if max_value is not None:
-            instance = self.model(value=max_value)
-            instance.full_clean()
-            instance.save()
-            qs = self.model.objects.filter(value__gte=max_value)
-            self.assertEqual(qs.count(), 1)
-            self.assertEqual(qs[0].value, max_value)
-
-    def test_backend_range_validation(self):
-        """
-        Ensure that backend specific range are enforced at the model
-        validation level. ref #12030.
-        """
-        min_value, max_value = self.backend_range
-
-        if min_value is not None:
-            instance = self.model(value=min_value - 1)
-            expected_message = validators.MinValueValidator.message % {
-                'limit_value': min_value
-            }
-            with self.assertRaisesMessage(ValidationError, expected_message):
-                instance.full_clean()
-            instance.value = min_value
-            instance.full_clean()
-
-        if max_value is not None:
-            instance = self.model(value=max_value + 1)
-            expected_message = validators.MaxValueValidator.message % {
-                'limit_value': max_value
-            }
-            with self.assertRaisesMessage(ValidationError, expected_message):
-                instance.full_clean()
-            instance.value = max_value
-            instance.full_clean()
-
-    def test_types(self):
-        instance = self.model(value=0)
-        self.assertIsInstance(instance.value, six.integer_types)
-        instance.save()
-        self.assertIsInstance(instance.value, six.integer_types)
-        instance = self.model.objects.get()
-        self.assertIsInstance(instance.value, six.integer_types)
-
-    def test_coercing(self):
-        self.model.objects.create(value='10')
-        instance = self.model.objects.get(value='10')
-        self.assertEqual(instance.value, 10)
-
-
-class SmallIntegerFieldTests(IntegerFieldTests):
-    model = SmallIntegerModel
-    documented_range = (-32768, 32767)
-
-
-class BigIntegerFieldTests(IntegerFieldTests):
-    model = BigIntegerModel
-    documented_range = (-9223372036854775808, 9223372036854775807)
-
-
-class PositiveSmallIntegerFieldTests(IntegerFieldTests):
-    model = PositiveSmallIntegerModel
-    documented_range = (0, 32767)
-
-
-class PositiveIntegerFieldTests(IntegerFieldTests):
-    model = PositiveIntegerModel
-    documented_range = (0, 2147483647)
-
-
-class TypeCoercionTests(test.TestCase):
-    """
-    Test that database lookups can accept the wrong types and convert
-    them with no error: especially on Postgres 8.3+ which does not do
-    automatic casting at the DB level. See #10015.
-    """
-    def test_lookup_integer_in_charfield(self):
-        self.assertEqual(Post.objects.filter(title=9).count(), 0)
-
-    def test_lookup_integer_in_textfield(self):
-        self.assertEqual(Post.objects.filter(body=24).count(), 0)
-
-
-class FileFieldTests(unittest.TestCase):
-    def test_clearable(self):
-        """
-        Test that FileField.save_form_data will clear its instance attribute
-        value if passed False.
-        """
-        d = Document(myfile='something.txt')
-        self.assertEqual(d.myfile, 'something.txt')
-        field = d._meta.get_field('myfile')
-        field.save_form_data(d, False)
-        self.assertEqual(d.myfile, '')
-
-    def test_unchanged(self):
-        """
-        Test that FileField.save_form_data considers None to mean "no change"
-        rather than "clear".
-        """
-        d = Document(myfile='something.txt')
-        self.assertEqual(d.myfile, 'something.txt')
-        field = d._meta.get_field('myfile')
-        field.save_form_data(d, None)
-        self.assertEqual(d.myfile, 'something.txt')
-
-    def test_changed(self):
-        """
-        Test that FileField.save_form_data, if passed a truthy value, updates
-        its instance attribute.
-        """
-        d = Document(myfile='something.txt')
-        self.assertEqual(d.myfile, 'something.txt')
-        field = d._meta.get_field('myfile')
-        field.save_form_data(d, 'else.txt')
-        self.assertEqual(d.myfile, 'else.txt')
-
-    def test_delete_when_file_unset(self):
-        """
-        Calling delete on an unset FileField should not call the file deletion
-        process, but fail silently (#20660).
-        """
-        d = Document()
-        try:
-            d.myfile.delete()
-        except OSError:
-            self.fail("Deleting an unset FileField should not raise OSError.")
-
-    def test_refresh_from_db(self):
-        d = Document.objects.create(myfile='something.txt')
-        d.refresh_from_db()
-        self.assertIs(d.myfile.instance, d)
-
-
-class BinaryFieldTests(test.TestCase):
-    binary_data = b'\x00\x46\xFE'
-
-    def test_set_and_retrieve(self):
-        data_set = (self.binary_data, six.memoryview(self.binary_data))
-        for bdata in data_set:
-            dm = DataModel(data=bdata)
-            dm.save()
-            dm = DataModel.objects.get(pk=dm.pk)
-            self.assertEqual(bytes(dm.data), bytes(bdata))
-            # Resave (=update)
-            dm.save()
-            dm = DataModel.objects.get(pk=dm.pk)
-            self.assertEqual(bytes(dm.data), bytes(bdata))
-            # Test default value
-            self.assertEqual(bytes(dm.short_data), b'\x08')
-
-    def test_max_length(self):
-        dm = DataModel(short_data=self.binary_data * 4)
-        with self.assertRaises(ValidationError):
-            dm.full_clean()
-
-
-class GenericIPAddressFieldTests(test.TestCase):
-    def test_genericipaddressfield_formfield_protocol(self):
-        """
-        Test that GenericIPAddressField with a specified protocol does not
-        generate a formfield with no specified protocol. See #20740.
-        """
-        model_field = models.GenericIPAddressField(protocol='IPv4')
-        form_field = model_field.formfield()
-        with self.assertRaises(ValidationError):
-            form_field.clean('::1')
-        model_field = models.GenericIPAddressField(protocol='IPv6')
-        form_field = model_field.formfield()
-        with self.assertRaises(ValidationError):
-            form_field.clean('127.0.0.1')
-
-    def test_null_value(self):
-        """
-        Null values should be resolved to None in Python (#24078).
-        """
-        GenericIPAddress.objects.create()
-        o = GenericIPAddress.objects.get()
-        self.assertIsNone(o.ip)
-
-    def test_save_load(self):
-        instance = GenericIPAddress.objects.create(ip='::1')
-        loaded = GenericIPAddress.objects.get()
-        self.assertEqual(loaded.ip, instance.ip)
-
-
-class PromiseTest(test.SimpleTestCase):
-    def test_AutoField(self):
-        lazy_func = lazy(lambda: 1, int)
-        self.assertIsInstance(
-            AutoField(primary_key=True).get_prep_value(lazy_func()),
-            int)
-
-    @unittest.skipIf(six.PY3, "Python 3 has no `long` type.")
-    def test_BigIntegerField(self):
-        # NOQA: long undefined on PY3
-        lazy_func = lazy(lambda: long(9999999999999999999), long)  # NOQA
-        self.assertIsInstance(
-            BigIntegerField().get_prep_value(lazy_func()),
-            long)  # NOQA
-
-    def test_BinaryField(self):
-        lazy_func = lazy(lambda: b'', bytes)
-        self.assertIsInstance(
-            BinaryField().get_prep_value(lazy_func()),
-            bytes)
-
-    def test_BooleanField(self):
-        lazy_func = lazy(lambda: True, bool)
-        self.assertIsInstance(
-            BooleanField().get_prep_value(lazy_func()),
-            bool)
-
-    def test_CharField(self):
-        lazy_func = lazy(lambda: '', six.text_type)
-        self.assertIsInstance(
-            CharField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            CharField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_CommaSeparatedIntegerField(self):
-        lazy_func = lazy(lambda: '1,2', six.text_type)
-        self.assertIsInstance(
-            CommaSeparatedIntegerField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            CommaSeparatedIntegerField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_DateField(self):
-        lazy_func = lazy(lambda: datetime.date.today(), datetime.date)
-        self.assertIsInstance(
-            DateField().get_prep_value(lazy_func()),
-            datetime.date)
-
-    def test_DateTimeField(self):
-        lazy_func = lazy(lambda: datetime.datetime.now(), datetime.datetime)
-        self.assertIsInstance(
-            DateTimeField().get_prep_value(lazy_func()),
-            datetime.datetime)
-
-    def test_DecimalField(self):
-        lazy_func = lazy(lambda: Decimal('1.2'), Decimal)
-        self.assertIsInstance(
-            DecimalField().get_prep_value(lazy_func()),
-            Decimal)
-
-    def test_EmailField(self):
-        lazy_func = lazy(lambda: 'mailbox@domain.com', six.text_type)
-        self.assertIsInstance(
-            EmailField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_FileField(self):
-        lazy_func = lazy(lambda: 'filename.ext', six.text_type)
-        self.assertIsInstance(
-            FileField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            FileField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_FilePathField(self):
-        lazy_func = lazy(lambda: 'tests.py', six.text_type)
-        self.assertIsInstance(
-            FilePathField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            FilePathField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_FloatField(self):
-        lazy_func = lazy(lambda: 1.2, float)
-        self.assertIsInstance(
-            FloatField().get_prep_value(lazy_func()),
-            float)
-
-    def test_ImageField(self):
-        lazy_func = lazy(lambda: 'filename.ext', six.text_type)
-        self.assertIsInstance(
-            ImageField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_IntegerField(self):
-        lazy_func = lazy(lambda: 1, int)
-        self.assertIsInstance(
-            IntegerField().get_prep_value(lazy_func()),
-            int)
-
-    def test_IPAddressField(self):
-        lazy_func = lazy(lambda: '127.0.0.1', six.text_type)
-        self.assertIsInstance(
-            IPAddressField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            IPAddressField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_GenericIPAddressField(self):
-        lazy_func = lazy(lambda: '127.0.0.1', six.text_type)
-        self.assertIsInstance(
-            GenericIPAddressField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            GenericIPAddressField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_NullBooleanField(self):
-        lazy_func = lazy(lambda: True, bool)
-        self.assertIsInstance(
-            NullBooleanField().get_prep_value(lazy_func()),
-            bool)
-
-    def test_PositiveIntegerField(self):
-        lazy_func = lazy(lambda: 1, int)
-        self.assertIsInstance(
-            PositiveIntegerField().get_prep_value(lazy_func()),
-            int)
-
-    def test_PositiveSmallIntegerField(self):
-        lazy_func = lazy(lambda: 1, int)
-        self.assertIsInstance(
-            PositiveSmallIntegerField().get_prep_value(lazy_func()),
-            int)
-
-    def test_SlugField(self):
-        lazy_func = lazy(lambda: 'slug', six.text_type)
-        self.assertIsInstance(
-            SlugField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            SlugField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_SmallIntegerField(self):
-        lazy_func = lazy(lambda: 1, int)
-        self.assertIsInstance(
-            SmallIntegerField().get_prep_value(lazy_func()),
-            int)
-
-    def test_TextField(self):
-        lazy_func = lazy(lambda: 'Abc', six.text_type)
-        self.assertIsInstance(
-            TextField().get_prep_value(lazy_func()),
-            six.text_type)
-        lazy_func = lazy(lambda: 0, int)
-        self.assertIsInstance(
-            TextField().get_prep_value(lazy_func()),
-            six.text_type)
-
-    def test_TimeField(self):
-        lazy_func = lazy(lambda: datetime.datetime.now().time(), datetime.time)
-        self.assertIsInstance(
-            TimeField().get_prep_value(lazy_func()),
-            datetime.time)
-
-    def test_URLField(self):
-        lazy_func = lazy(lambda: 'http://domain.com', six.text_type)
-        self.assertIsInstance(
-            URLField().get_prep_value(lazy_func()),
-            six.text_type)
-
-
-class CustomFieldTests(unittest.TestCase):
-
-    def test_14786(self):
-        """
-        Regression test for #14786 -- Test that field values are not prepared
-        twice in get_db_prep_lookup().
-        """
-        class NoopField(models.TextField):
-            def __init__(self, *args, **kwargs):
-                self.prep_value_count = 0
-                super(NoopField, self).__init__(*args, **kwargs)
-
-            def get_prep_value(self, value):
-                self.prep_value_count += 1
-                return super(NoopField, self).get_prep_value(value)
-
-        field = NoopField()
-        field.get_db_prep_lookup(
-            'exact', 'TEST', connection=connection, prepared=False
-        )
-        self.assertEqual(field.prep_value_count, 1)