the bug is that the following queries would raise typeerror related field has invalid lookup gte regression test for 10153 foreign key gte lookups regression test for 10153 foreign key lte lookups regression test for 14019 sqlinsertcompiler assql failure this line will raise an attributeerror without the accompanying fix note part of the regression test here is merely parsing the model declaration the verbosename in particular did not always work an empty choice field should return none for the display name empty strings should be returned as string textfields can hold more than 4000 characters this was broken in oracle textfields can hold more than 4000 bytes also when they are less than 4000 characters regression test for 659 regression test for 8510 regression test for 18969 date filtering was failing with null date values in sqlite regression test for 3501 among other things getnextbyfield and getpreviousbyfield don t crash when microseconds values are stored in the database check department and worker nondefault pk type saving and updating with timezoneaware datetime python objects regression test for 10443 the idea is that all these creations and saving should work without crashing it s not rocket science chained foreign keys with tofield produce incorrect query this is the actual test for 18432 model metaclasses have access to the class attribute dict in init 30254 regression test for 13640 cannot filter by objects with evaluate attr you can filter by objects that have an evaluate attr changing related fields doesn t mutate the base object the bug is that the following queries would raise typeerror related field has invalid lookup gte regression test for 10153 foreign key __gte lookups regression test for 10153 foreign key __lte lookups regression test for 14019 sqlinsertcompiler as_sql failure this line will raise an attributeerror without the accompanying fix note part of the regression test here is merely parsing the model declaration the verbose_name in particular did not always work an empty choice field should return none for the display name empty strings should be returned as string textfields can hold more than 4000 characters this was broken in oracle textfields can hold more than 4000 bytes also when they are less than 4000 characters regression test for 659 regression test for 8510 regression test for 18969 date filtering was failing with null date values in sqlite regression test for 3501 among other things get_next_by_field and get_previous_by_field don t crash when microseconds values are stored in the database check department and worker non default pk type saving and updating with timezone aware datetime python objects regression test for 10443 the idea is that all these creations and saving should work without crashing it s not rocket science chained foreign keys with to_field produce incorrect query this is the actual test for 18432 model metaclasses have access to the class attribute dict in __init__ 30254 regression test for 13640 cannot filter by objects with evaluate attr you can filter by objects that have an evaluate attr changing related fields doesn t mutate the base object
import copy
import datetime
from operator import attrgetter

from django.core.exceptions import ValidationError
from django.db import models, router
from django.db.models.sql import InsertQuery
from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import isolate_apps
from django.utils.timezone import get_fixed_timezone

from .models import (
    Article,
    Department,
    Event,
    Model1,
    Model2,
    Model3,
    NonAutoPK,
    Party,
    Worker,
)


class ModelTests(TestCase):
    def test_model_init_too_many_args(self):
        msg = "Number of args exceeds number of fields"
        with self.assertRaisesMessage(IndexError, msg):
            Worker(1, 2, 3, 4)

    
    
    def test_related_gte_lookup(self):
        
        Worker.objects.filter(department__gte=0)

    def test_related_lte_lookup(self):
        
        Worker.objects.filter(department__lte=0)

    def test_sql_insert_compiler_return_id_attribute(self):
        
        db = router.db_for_write(Party)
        query = InsertQuery(Party)
        query.insert_values([Party._meta.fields[0]], [], raw=False)
        
        query.get_compiler(using=db).as_sql()

    def test_empty_choice(self):
        
        
        a = Article.objects.create(
            headline="Look at me!", pub_date=datetime.datetime.now()
        )
        
        self.assertIs(a.get_status_display(), None)

        
        a = Article.objects.get(pk=a.pk)
        self.assertEqual(a.misc_data, "")

    def test_long_textfield(self):
        
        
        a = Article.objects.create(
            headline="Really, really big",
            pub_date=datetime.datetime.now(),
            article_text="ABCDE" * 1000,
        )
        a = Article.objects.get(pk=a.pk)
        self.assertEqual(len(a.article_text), 5000)

    def test_long_unicode_textfield(self):
        
        
        a = Article.objects.create(
            headline="Really, really big",
            pub_date=datetime.datetime.now(),
            article_text="\u05d0\u05d1\u05d2" * 1000,
        )
        a = Article.objects.get(pk=a.pk)
        self.assertEqual(len(a.article_text), 3000)

    def test_date_lookup(self):
        
        Party.objects.create(when=datetime.datetime(1999, 12, 31))
        Party.objects.create(when=datetime.datetime(1998, 12, 31))
        Party.objects.create(when=datetime.datetime(1999, 1, 1))
        Party.objects.create(when=datetime.datetime(1, 3, 3))
        self.assertQuerySetEqual(Party.objects.filter(when__month=2), [])
        self.assertQuerySetEqual(
            Party.objects.filter(when__month=1),
            [datetime.date(1999, 1, 1)],
            attrgetter("when"),
        )
        self.assertQuerySetEqual(
            Party.objects.filter(when__month=12),
            [
                datetime.date(1999, 12, 31),
                datetime.date(1998, 12, 31),
            ],
            attrgetter("when"),
            ordered=False,
        )
        self.assertQuerySetEqual(
            Party.objects.filter(when__year=1998),
            [
                datetime.date(1998, 12, 31),
            ],
            attrgetter("when"),
        )
        
        self.assertQuerySetEqual(
            Party.objects.filter(when__day="31"),
            [
                datetime.date(1999, 12, 31),
                datetime.date(1998, 12, 31),
            ],
            attrgetter("when"),
            ordered=False,
        )
        self.assertQuerySetEqual(
            Party.objects.filter(when__month="12"),
            [
                datetime.date(1999, 12, 31),
                datetime.date(1998, 12, 31),
            ],
            attrgetter("when"),
            ordered=False,
        )
        self.assertQuerySetEqual(
            Party.objects.filter(when__year="1998"),
            [
                datetime.date(1998, 12, 31),
            ],
            attrgetter("when"),
        )

        
        self.assertQuerySetEqual(
            Party.objects.filter(when__year=1),
            [
                datetime.date(1, 3, 3),
            ],
            attrgetter("when"),
        )
        self.assertQuerySetEqual(
            Party.objects.filter(when__year="1"),
            [
                datetime.date(1, 3, 3),
            ],
            attrgetter("when"),
        )

    def test_date_filter_null(self):
        
        
        Party.objects.create(when=datetime.datetime(1999, 1, 1))
        Party.objects.create()
        p = Party.objects.filter(when__month=1)[0]
        self.assertEqual(p.when, datetime.date(1999, 1, 1))
        self.assertQuerySetEqual(
            Party.objects.filter(pk=p.pk).dates("when", "month"),
            [1],
            attrgetter("month"),
        )

    def test_get_next_prev_by_field(self):
        
        
        Event.objects.create(when=datetime.datetime(2000, 1, 1, 16, 0, 0))
        Event.objects.create(when=datetime.datetime(2000, 1, 1, 6, 1, 1))
        Event.objects.create(when=datetime.datetime(2000, 1, 1, 13, 1, 1))
        e = Event.objects.create(when=datetime.datetime(2000, 1, 1, 12, 0, 20, 24))
        self.assertEqual(
            e.get_next_by_when().when, datetime.datetime(2000, 1, 1, 13, 1, 1)
        )
        self.assertEqual(
            e.get_previous_by_when().when, datetime.datetime(2000, 1, 1, 6, 1, 1)
        )

    def test_get_next_prev_by_field_unsaved(self):
        msg = "get_next/get_previous cannot be used on unsaved objects."
        with self.assertRaisesMessage(ValueError, msg):
            Event().get_next_by_when()
        with self.assertRaisesMessage(ValueError, msg):
            Event().get_previous_by_when()

    def test_primary_key_foreign_key_types(self):
        
        d = Department.objects.create(id=10, name="IT")
        w = Worker.objects.create(department=d, name="Full-time")
        self.assertEqual(str(w), "Full-time")

    @skipUnlessDBFeature("supports_timezones")
    def test_timezones(self):
        
        
        
        
        dt1 = datetime.datetime(2008, 8, 31, 16, 20, tzinfo=get_fixed_timezone(600))
        dt2 = datetime.datetime(2008, 8, 31, 17, 20, tzinfo=get_fixed_timezone(600))
        obj = Article.objects.create(
            headline="A headline", pub_date=dt1, article_text="foo"
        )
        obj.pub_date = dt2
        obj.save()
        self.assertEqual(
            Article.objects.filter(headline="A headline").update(pub_date=dt1), 1
        )

    def test_chained_fks(self):
        

        m1 = Model1.objects.create(pkey=1000)
        m2 = Model2.objects.create(model1=m1)
        m3 = Model3.objects.create(model2=m2)

        
        m3 = Model3.objects.get(model2=1000)
        m3.model2

    @isolate_apps("model_regress")
    def test_metaclass_can_access_attribute_dict(self):
        

        class HorseBase(models.base.ModelBase):
            def __init__(cls, name, bases, attrs):
                super().__init__(name, bases, attrs)
                cls.horns = 1 if "magic" in attrs else 0

        class Horse(models.Model, metaclass=HorseBase):
            name = models.CharField(max_length=255)
            magic = True

        self.assertEqual(Horse.horns, 1)


class ModelValidationTest(TestCase):
    def test_pk_validation(self):
        NonAutoPK.objects.create(name="one")
        again = NonAutoPK(name="one")
        with self.assertRaises(ValidationError):
            again.validate_unique()


class EvaluateMethodTest(TestCase):
    

    def test_model_with_evaluate_method(self):
        
        dept = Department.objects.create(pk=1, name="abc")
        dept.evaluate = "abc"
        Worker.objects.filter(department=dept)


class ModelFieldsCacheTest(TestCase):
    def test_fields_cache_reset_on_copy(self):
        department1 = Department.objects.create(id=1, name="department1")
        department2 = Department.objects.create(id=2, name="department2")
        worker1 = Worker.objects.create(name="worker", department=department1)
        worker2 = copy.copy(worker1)

        self.assertEqual(worker2.department, department1)
        
        worker2.department = department2
        self.assertEqual(worker2.department, department2)
        self.assertEqual(worker1.department, department1)