FIxed #7666: use a bare queryset when accessing single related objects so that the related objects never become inaccessible.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8017 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jacob Kaplan-Moss 2008-07-21 15:41:21 +00:00
parent 4016d5264a
commit 970611827b
3 changed files with 45 additions and 1 deletions

View File

@ -2,6 +2,7 @@ from django.db import connection, transaction
from django.db.models import signals, get_model from django.db.models import signals, get_model
from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist
from django.db.models.related import RelatedObject from django.db.models.related import RelatedObject
from django.db.models.query import QuerySet
from django.db.models.query_utils import QueryWrapper from django.db.models.query_utils import QueryWrapper
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _ from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _
@ -236,7 +237,7 @@ class ReverseSingleRelatedObjectDescriptor(object):
params = {'%s__pk' % self.field.rel.field_name: val} params = {'%s__pk' % self.field.rel.field_name: val}
else: else:
params = {'%s__exact' % self.field.rel.field_name: val} params = {'%s__exact' % self.field.rel.field_name: val}
rel_obj = self.field.rel.to._default_manager.get(**params) rel_obj = QuerySet(self.field.rel.to).get(**params)
setattr(instance, cache_name, rel_obj) setattr(instance, cache_name, rel_obj)
return rel_obj return rel_obj

View File

@ -0,0 +1,43 @@
"""
Regression tests for an object that cannot access a single related object due
to a restrictive default manager.
"""
from django.db import models
class SourceManager(models.Manager):
def get_query_set(self):
return super(SourceManager, self).get_query_set().filter(is_public=True)
class Source(models.Model):
is_public = models.BooleanField()
objects = SourceManager()
class Item(models.Model):
source = models.ForeignKey(Source)
__test__ = {'API_TESTS':"""
>>> public_source = Source.objects.create(is_public=True)
>>> public_item = Item.objects.create(source=public_source)
>>> private_source = Source.objects.create(is_public=False)
>>> private_item = Item.objects.create(source=private_source)
Only one source is available via all() due to the custom default manager.
>>> Source.objects.all()
[<Source: Source object>]
>>> public_item.source
<Source: Source object>
Make sure that an item can still access its related source even if the default
manager doesn't normally allow it.
>>> private_item.source
<Source: Source object>
"""}