1
0
mirror of https://github.com/django/django.git synced 2025-10-24 14:16:09 +00:00

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.
This commit is contained in:
Loic Bistuer
2014-09-24 00:41:32 +07:00
parent 1fd6e13bf2
commit e043aae9bb
3 changed files with 90 additions and 15 deletions

View File

@@ -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'))