Merged custom_managers_regress into the custom_managers test package.

This commit is contained in:
Loic Bistuer 2014-09-23 01:23:34 +07:00
parent d42a45de40
commit 0dab07e5da
5 changed files with 86 additions and 109 deletions

View File

@ -11,28 +11,20 @@ returns.
from __future__ import unicode_literals from __future__ import unicode_literals
from django.contrib.contenttypes.fields import ( from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
GenericForeignKey, GenericRelation
)
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
# An example of a custom manager called "objects".
class PersonManager(models.Manager): class PersonManager(models.Manager):
def get_fun_people(self): def get_fun_people(self):
return self.filter(fun=True) return self.filter(fun=True)
# An example of a custom manager that sets get_queryset().
class PublishedBookManager(models.Manager): class PublishedBookManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(PublishedBookManager, self).get_queryset().filter(is_published=True) return super(PublishedBookManager, self).get_queryset().filter(is_published=True)
# An example of a custom queryset that copies its methods onto the manager.
class CustomQuerySet(models.QuerySet): class CustomQuerySet(models.QuerySet):
def filter(self, *args, **kwargs): def filter(self, *args, **kwargs):
@ -138,8 +130,6 @@ class Book(models.Model):
def __str__(self): def __str__(self):
return self.title return self.title
# An example of providing multiple custom managers.
class FastCarManager(models.Manager): class FastCarManager(models.Manager):
def get_queryset(self): def get_queryset(self):
@ -156,3 +146,42 @@ class Car(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
class RestrictedManager(models.Manager):
def get_queryset(self):
return super(RestrictedManager, self).get_queryset().filter(is_public=True)
@python_2_unicode_compatible
class RelatedModel(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
@python_2_unicode_compatible
class RestrictedModel(models.Model):
name = models.CharField(max_length=50)
is_public = models.BooleanField(default=False)
related = models.ForeignKey(RelatedModel)
objects = RestrictedManager()
plain_manager = models.Manager()
def __str__(self):
return self.name
@python_2_unicode_compatible
class OneToOneRestrictedModel(models.Model):
name = models.CharField(max_length=50)
is_public = models.BooleanField(default=False)
related = models.OneToOneField(RelatedModel)
objects = RestrictedManager()
plain_manager = models.Manager()
def __str__(self):
return self.name

View File

@ -3,7 +3,8 @@ from __future__ import unicode_literals
from django.test import TestCase from django.test import TestCase
from django.utils import six from django.utils import six
from .models import Person, FunPerson, Book, Car, PersonManager, PublishedBookManager from .models import (Book, Car, FunPerson, OneToOneRestrictedModel, Person,
PersonManager, PublishedBookManager, RelatedModel, RestrictedModel)
class CustomManagerTests(TestCase): class CustomManagerTests(TestCase):
@ -463,3 +464,47 @@ class CustomManagerTests(TestCase):
lambda c: c.first_name, lambda c: c.first_name,
ordered=False, ordered=False,
) )
class CustomManagersRegressTestCase(TestCase):
def test_filtered_default_manager(self):
"""Even though the default manager filters out some records,
we must still be able to save (particularly, save by updating
existing records) those filtered instances. This is a
regression test for #8990, #9527"""
related = RelatedModel.objects.create(name="xyzzy")
obj = RestrictedModel.objects.create(name="hidden", related=related)
obj.name = "still hidden"
obj.save()
# If the hidden object wasn't seen during the save process,
# there would now be two objects in the database.
self.assertEqual(RestrictedModel.plain_manager.count(), 1)
def test_delete_related_on_filtered_manager(self):
"""Deleting related objects should also not be distracted by a
restricted manager on the related object. This is a regression
test for #2698."""
related = RelatedModel.objects.create(name="xyzzy")
for name, public in (('one', True), ('two', False), ('three', False)):
RestrictedModel.objects.create(name=name, is_public=public, related=related)
obj = RelatedModel.objects.get(name="xyzzy")
obj.delete()
# All of the RestrictedModel instances should have been
# deleted, since they *all* pointed to the RelatedModel. If
# the default manager is used, only the public one will be
# deleted.
self.assertEqual(len(RestrictedModel.plain_manager.all()), 0)
def test_delete_one_to_one_manager(self):
# The same test case as the last one, but for one-to-one
# models, which are implemented slightly different internally,
# so it's a different code path.
obj = RelatedModel.objects.create(name="xyzzy")
OneToOneRestrictedModel.objects.create(name="foo", is_public=False, related=obj)
obj = RelatedModel.objects.get(name="xyzzy")
obj.delete()
self.assertEqual(len(OneToOneRestrictedModel.plain_manager.all()), 0)

View File

@ -1,48 +0,0 @@
"""
Regression tests for custom manager classes.
"""
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
class RestrictedManager(models.Manager):
"""
A manager that filters out non-public instances.
"""
def get_queryset(self):
return super(RestrictedManager, self).get_queryset().filter(is_public=True)
@python_2_unicode_compatible
class RelatedModel(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
@python_2_unicode_compatible
class RestrictedModel(models.Model):
name = models.CharField(max_length=50)
is_public = models.BooleanField(default=False)
related = models.ForeignKey(RelatedModel)
objects = RestrictedManager()
plain_manager = models.Manager()
def __str__(self):
return self.name
@python_2_unicode_compatible
class OneToOneRestrictedModel(models.Model):
name = models.CharField(max_length=50)
is_public = models.BooleanField(default=False)
related = models.OneToOneField(RelatedModel)
objects = RestrictedManager()
plain_manager = models.Manager()
def __str__(self):
return self.name

View File

@ -1,49 +0,0 @@
from __future__ import unicode_literals
from django.test import TestCase
from .models import RelatedModel, RestrictedModel, OneToOneRestrictedModel
class CustomManagersRegressTestCase(TestCase):
def test_filtered_default_manager(self):
"""Even though the default manager filters out some records,
we must still be able to save (particularly, save by updating
existing records) those filtered instances. This is a
regression test for #8990, #9527"""
related = RelatedModel.objects.create(name="xyzzy")
obj = RestrictedModel.objects.create(name="hidden", related=related)
obj.name = "still hidden"
obj.save()
# If the hidden object wasn't seen during the save process,
# there would now be two objects in the database.
self.assertEqual(RestrictedModel.plain_manager.count(), 1)
def test_delete_related_on_filtered_manager(self):
"""Deleting related objects should also not be distracted by a
restricted manager on the related object. This is a regression
test for #2698."""
related = RelatedModel.objects.create(name="xyzzy")
for name, public in (('one', True), ('two', False), ('three', False)):
RestrictedModel.objects.create(name=name, is_public=public, related=related)
obj = RelatedModel.objects.get(name="xyzzy")
obj.delete()
# All of the RestrictedModel instances should have been
# deleted, since they *all* pointed to the RelatedModel. If
# the default manager is used, only the public one will be
# deleted.
self.assertEqual(len(RestrictedModel.plain_manager.all()), 0)
def test_delete_one_to_one_manager(self):
# The same test case as the last one, but for one-to-one
# models, which are implemented slightly different internally,
# so it's a different code path.
obj = RelatedModel.objects.create(name="xyzzy")
OneToOneRestrictedModel.objects.create(name="foo", is_public=False, related=obj)
obj = RelatedModel.objects.get(name="xyzzy")
obj.delete()
self.assertEqual(len(OneToOneRestrictedModel.plain_manager.all()), 0)