django/tests/managers_regress/tests.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

304 lines
11 KiB
Python
Raw Normal View History

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])
# Since Child6 inherits from Child4, the corresponding rows from f1 and
# f2 also appear here. This is the expected result.
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):
# 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.
msg = "type object 'AbstractBase3' has no attribute 'objects'"
with self.assertRaisesMessage(AttributeError, msg):
AbstractBase3.objects.all()
def test_custom_abstract_manager(self):
# Accessing the manager on an abstract model with a custom
# manager should raise an attribute error with an appropriate
# message.
msg = "Manager isn't available; AbstractBase2 is abstract"
with self.assertRaisesMessage(AttributeError, msg):
AbstractBase2.restricted.all()
def test_explicit_abstract_manager(self):
# Accessing the manager on an abstract model with an explicit
# manager should raise an attribute error with an appropriate
# message.
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"
# Accessing the manager on a swappable model should
# raise an attribute error with a helpful message
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"
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
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"
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
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):
# 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.
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)