since child6 inherits from child4 the corresponding rows from f1 and f2 also appear here this is the expected result accessing the manager on an abstract model should raise an attribute error with an appropriate message this error message isn t ideal but if the model is abstract and a lot of the class instantiation logic isn t invoked if the manager is implied then we don t get a hook to install the errorraising manager accessing the manager on an abstract model with a custom manager should raise an attribute error with an appropriate message accessing the manager on an abstract model with an explicit manager should raise an attribute error with an appropriate message accessing the manager on a swappable model should raise an attribute error with a helpful message accessing the manager on a swappable model with an explicit manager should raise an attribute error with a helpful message accessing the manager on a swappable model with an explicit manager should raise an attribute error with a helpful message make sure related managers core filters don t include an explicit exact lookup that could be interpreted as a reference to a foreign exact field refs 23940 since child6 inherits from child4 the corresponding rows from f1 and f2 also appear here this is the expected result accessing the manager on an abstract model should raise an attribute error with an appropriate message this error message isn t ideal but if the model is abstract and a lot of the class instantiation logic isn t invoked if the manager is implied then we don t get a hook to install the error raising manager accessing the manager on an abstract model with a custom manager should raise an attribute error with an appropriate message accessing the manager on an abstract model with an explicit manager should raise an attribute error with an appropriate message accessing the manager on a swappable model should raise an attribute error with a helpful message accessing the manager on a swappable model with an explicit manager should raise an attribute error with a helpful message accessing the manager on a swappable model with an explicit manager should raise an attribute error with a helpful message make sure related managers core filters don t include an explicit __exact lookup that could be interpreted as a reference to a foreign exact field refs 23940
from django.db import models
from django.template import Context, Template
from django.test import SimpleTestCase, TestCase, override_settings
from django.test.utils import isolate_apps

from .models import (
    AbstractBase1,
    AbstractBase2,
    AbstractBase3,
    Child1,
    Child2,
    Child3,
    Child4,
    Child5,
    Child6,
    Child7,
    RelatedModel,
    RelationModel,
)


class ManagersRegressionTests(TestCase):
    def test_managers(self):
        a1 = Child1.objects.create(name="fred", data="a1")
        a2 = Child1.objects.create(name="barney", data="a2")
        b1 = Child2.objects.create(name="fred", data="b1", value=1)
        b2 = Child2.objects.create(name="barney", data="b2", value=42)
        c1 = Child3.objects.create(name="fred", data="c1", comment="yes")
        c2 = Child3.objects.create(name="barney", data="c2", comment="no")
        d1 = Child4.objects.create(name="fred", data="d1")
        d2 = Child4.objects.create(name="barney", data="d2")
        fred1 = Child5.objects.create(name="fred", comment="yes")
        Child5.objects.create(name="barney", comment="no")
        f1 = Child6.objects.create(name="fred", data="f1", value=42)
        f2 = Child6.objects.create(name="barney", data="f2", value=42)
        fred2 = Child7.objects.create(name="fred")
        barney = Child7.objects.create(name="barney")

        self.assertSequenceEqual(Child1.manager1.all(), [a1])
        self.assertSequenceEqual(Child1.manager2.all(), [a2])
        self.assertSequenceEqual(Child1._default_manager.all(), [a1])

        self.assertSequenceEqual(Child2._default_manager.all(), [b1])
        self.assertSequenceEqual(Child2.restricted.all(), [b2])

        self.assertSequenceEqual(Child3._default_manager.all(), [c1])
        self.assertSequenceEqual(Child3.manager1.all(), [c1])
        self.assertSequenceEqual(Child3.manager2.all(), [c2])

        
        
        self.assertSequenceEqual(
            Child4._default_manager.order_by("data"),
            [d1, d2, f1.child4_ptr, f2.child4_ptr],
        )
        self.assertCountEqual(Child4.manager1.all(), [d1, f1.child4_ptr])
        self.assertCountEqual(Child5._default_manager.all(), [fred1])
        self.assertCountEqual(Child6._default_manager.all(), [f1, f2])
        self.assertSequenceEqual(
            Child7._default_manager.order_by("name"),
            [barney, fred2],
        )

    def test_abstract_manager(self):
        
        
        
        
        
        
        msg = "type object 'AbstractBase3' has no attribute 'objects'"
        with self.assertRaisesMessage(AttributeError, msg):
            AbstractBase3.objects.all()

    def test_custom_abstract_manager(self):
        
        
        
        msg = "Manager isn't available; AbstractBase2 is abstract"
        with self.assertRaisesMessage(AttributeError, msg):
            AbstractBase2.restricted.all()

    def test_explicit_abstract_manager(self):
        
        
        
        msg = "Manager isn't available; AbstractBase1 is abstract"
        with self.assertRaisesMessage(AttributeError, msg):
            AbstractBase1.objects.all()

    @override_settings(TEST_SWAPPABLE_MODEL="managers_regress.Parent")
    @isolate_apps("managers_regress")
    def test_swappable_manager(self):
        class SwappableModel(models.Model):
            class Meta:
                swappable = "TEST_SWAPPABLE_MODEL"

        
        
        msg = (
            "Manager isn't available; 'managers_regress.SwappableModel' "
            "has been swapped for 'managers_regress.Parent'"
        )
        with self.assertRaisesMessage(AttributeError, msg):
            SwappableModel.objects.all()

    @override_settings(TEST_SWAPPABLE_MODEL="managers_regress.Parent")
    @isolate_apps("managers_regress")
    def test_custom_swappable_manager(self):
        class SwappableModel(models.Model):
            stuff = models.Manager()

            class Meta:
                swappable = "TEST_SWAPPABLE_MODEL"

        
        
        
        msg = (
            "Manager isn't available; 'managers_regress.SwappableModel' "
            "has been swapped for 'managers_regress.Parent'"
        )
        with self.assertRaisesMessage(AttributeError, msg):
            SwappableModel.stuff.all()

    @override_settings(TEST_SWAPPABLE_MODEL="managers_regress.Parent")
    @isolate_apps("managers_regress")
    def test_explicit_swappable_manager(self):
        class SwappableModel(models.Model):
            objects = models.Manager()

            class Meta:
                swappable = "TEST_SWAPPABLE_MODEL"

        
        
        
        msg = (
            "Manager isn't available; 'managers_regress.SwappableModel' "
            "has been swapped for 'managers_regress.Parent'"
        )
        with self.assertRaisesMessage(AttributeError, msg):
            SwappableModel.objects.all()

    def test_regress_3871(self):
        related = RelatedModel.objects.create()

        relation = RelationModel()
        relation.fk = related
        relation.gfk = related
        relation.save()
        relation.m2m.add(related)

        t = Template(
            "{{ related.test_fk.all.0 }}{{ related.test_gfk.all.0 }}"
            "{{ related.test_m2m.all.0 }}"
        )

        self.assertEqual(
            t.render(Context({"related": related})),
            "".join([str(relation.pk)] * 3),
        )

    def test_field_can_be_called_exact(self):
        
        
        
        related = RelatedModel.objects.create(exact=False)
        relation = related.test_fk.create()
        self.assertEqual(related.test_fk.get(), relation)


@isolate_apps("managers_regress")
class TestManagerInheritance(SimpleTestCase):
    def test_implicit_inheritance(self):
        class CustomManager(models.Manager):
            pass

        class AbstractModel(models.Model):
            custom_manager = CustomManager()

            class Meta:
                abstract = True

        class PlainModel(models.Model):
            custom_manager = CustomManager()

        self.assertIsInstance(PlainModel._base_manager, models.Manager)
        self.assertIsInstance(PlainModel._default_manager, CustomManager)

        class ModelWithAbstractParent(AbstractModel):
            pass

        self.assertIsInstance(ModelWithAbstractParent._base_manager, models.Manager)
        self.assertIsInstance(ModelWithAbstractParent._default_manager, CustomManager)

        class ProxyModel(PlainModel):
            class Meta:
                proxy = True

        self.assertIsInstance(ProxyModel._base_manager, models.Manager)
        self.assertIsInstance(ProxyModel._default_manager, CustomManager)

        class MTIModel(PlainModel):
            pass

        self.assertIsInstance(MTIModel._base_manager, models.Manager)
        self.assertIsInstance(MTIModel._default_manager, CustomManager)

    def test_default_manager_inheritance(self):
        class CustomManager(models.Manager):
            pass

        class AbstractModel(models.Model):
            another_manager = models.Manager()
            custom_manager = CustomManager()

            class Meta:
                default_manager_name = "custom_manager"
                abstract = True

        class PlainModel(models.Model):
            another_manager = models.Manager()
            custom_manager = CustomManager()

            class Meta:
                default_manager_name = "custom_manager"

        self.assertIsInstance(PlainModel._default_manager, CustomManager)

        class ModelWithAbstractParent(AbstractModel):
            pass

        self.assertIsInstance(ModelWithAbstractParent._default_manager, CustomManager)

        class ProxyModel(PlainModel):
            class Meta:
                proxy = True

        self.assertIsInstance(ProxyModel._default_manager, CustomManager)

        class MTIModel(PlainModel):
            pass

        self.assertIsInstance(MTIModel._default_manager, CustomManager)

    def test_base_manager_inheritance(self):
        class CustomManager(models.Manager):
            pass

        class AbstractModel(models.Model):
            another_manager = models.Manager()
            custom_manager = CustomManager()

            class Meta:
                base_manager_name = "custom_manager"
                abstract = True

        class PlainModel(models.Model):
            another_manager = models.Manager()
            custom_manager = CustomManager()

            class Meta:
                base_manager_name = "custom_manager"

        self.assertIsInstance(PlainModel._base_manager, CustomManager)

        class ModelWithAbstractParent(AbstractModel):
            pass

        self.assertIsInstance(ModelWithAbstractParent._base_manager, CustomManager)

        class ProxyModel(PlainModel):
            class Meta:
                proxy = True

        self.assertIsInstance(ProxyModel._base_manager, CustomManager)

        class MTIModel(PlainModel):
            pass

        self.assertIsInstance(MTIModel._base_manager, CustomManager)

    def test_manager_no_duplicates(self):
        class CustomManager(models.Manager):
            pass

        class AbstractModel(models.Model):
            custom_manager = models.Manager()

            class Meta:
                abstract = True

        class TestModel(AbstractModel):
            custom_manager = CustomManager()

        self.assertEqual(TestModel._meta.managers, (TestModel.custom_manager,))
        self.assertEqual(
            TestModel._meta.managers_map, {"custom_manager": TestModel.custom_manager}
        )

    def test_manager_class_getitem(self):
        self.assertIs(models.Manager[Child1], models.Manager)