diff options
author | Loic Bistuer <loic.bistuer@gmail.com> | 2014-09-24 00:41:32 +0700 |
---|---|---|
committer | Loic Bistuer <loic.bistuer@gmail.com> | 2014-09-24 02:03:12 +0700 |
commit | e043aae9bb2e3fa244f59b07fc16f57476cb80ff (patch) | |
tree | 333f0f9d349f150692c63280c06cd655f371c5cd /tests/one_to_one | |
parent | 1fd6e13bf2db025dc93482184439cc1a900db276 (diff) | |
download | django-e043aae9bb2e3fa244f59b07fc16f57476cb80ff.tar.gz |
Fixed #23550 -- Normalized get_queryset() of RelatedObjectDescriptor
and ReverseSingleRelatedObjectDescriptor so they actually return QuerySet
instances.
Also ensured that SingleRelatedObjectDescriptor.get_queryset() accounts
for use_for_related_fields=True.
This cleanup lays the groundwork for #23533.
Thanks Anssi Kääriäinen for the review.
Diffstat (limited to 'tests/one_to_one')
-rw-r--r-- | tests/one_to_one/models.py | 21 | ||||
-rw-r--r-- | tests/one_to_one/tests.py | 58 |
2 files changed, 78 insertions, 1 deletions
diff --git a/tests/one_to_one/models.py b/tests/one_to_one/models.py index ccb6851bc3..88b0ef6dcf 100644 --- a/tests/one_to_one/models.py +++ b/tests/one_to_one/models.py @@ -96,3 +96,24 @@ class Pointer2(models.Model): class HiddenPointer(models.Model): target = models.OneToOneField(Target, related_name='hidden+') + + +# Test related objects visibility. +class SchoolManager(models.Manager): + def get_queryset(self): + return super(SchoolManager, self).get_queryset().filter(is_public=True) + + +class School(models.Model): + is_public = models.BooleanField(default=False) + objects = SchoolManager() + + +class DirectorManager(models.Manager): + def get_queryset(self): + return super(DirectorManager, self).get_queryset().filter(is_temp=False) + +class Director(models.Model): + is_temp = models.BooleanField(default=False) + school = models.OneToOneField(School) + objects = DirectorManager() diff --git a/tests/one_to_one/tests.py b/tests/one_to_one/tests.py index da0fb5259f..d9eef0b133 100644 --- a/tests/one_to_one/tests.py +++ b/tests/one_to_one/tests.py @@ -4,7 +4,7 @@ from django.db import transaction, IntegrityError, connection from django.test import TestCase from .models import (Bar, Favorites, HiddenPointer, ManualPrimaryKey, MultiModel, - Place, RelatedModel, Restaurant, Target, UndergroundBar, Waiter) + Place, RelatedModel, Restaurant, School, Director, Target, UndergroundBar, Waiter) class OneToOneTests(TestCase): @@ -382,3 +382,59 @@ class OneToOneTests(TestCase): self.assertFalse( hasattr(Target, HiddenPointer._meta.get_field('target').related.get_accessor_name()) ) + + def test_related_object(self): + public_school = School.objects.create(is_public=True) + public_director = Director.objects.create(school=public_school, is_temp=False) + + private_school = School.objects.create(is_public=False) + private_director = Director.objects.create(school=private_school, is_temp=True) + + # Only one school is available via all() due to the custom default manager. + self.assertQuerysetEqual( + School.objects.all(), + ["<School: School object>"] + ) + + # Only one director is available via all() due to the custom default manager. + self.assertQuerysetEqual( + Director.objects.all(), + ["<Director: Director object>"] + ) + + self.assertEqual(public_director.school, public_school) + self.assertEqual(public_school.director, public_director) + + # Make sure the base manager is used so that the related objects + # is still accessible even if the default manager doesn't normally + # allow it. + self.assertEqual(private_director.school, private_school) + + # Make sure the base manager is used so that an student can still access + # its related school even if the default manager doesn't normally + # allow it. + self.assertEqual(private_school.director, private_director) + + # If the manager is marked "use_for_related_fields", it'll get used instead + # of the "bare" queryset. Usually you'd define this as a property on the class, + # but this approximates that in a way that's easier in tests. + School.objects.use_for_related_fields = True + try: + private_director = Director._base_manager.get(pk=private_director.pk) + self.assertRaises(School.DoesNotExist, lambda: private_director.school) + finally: + School.objects.use_for_related_fields = False + + Director.objects.use_for_related_fields = True + try: + private_school = School._base_manager.get(pk=private_school.pk) + self.assertRaises(Director.DoesNotExist, lambda: private_school.director) + finally: + Director.objects.use_for_related_fields = False + + def test_hasattr_related_object(self): + # The exception raised on attribute access when a related object + # doesn't exist should be an instance of a subclass of `AttributeError` + # refs #21563 + self.assertFalse(hasattr(Director(), 'director')) + self.assertFalse(hasattr(School(), 'school')) |