summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2012-04-10 12:29:25 +0000
committerAymeric Augustin <aymeric.augustin@m4x.org>2012-04-10 12:29:25 +0000
commitb90d4e5b749be3b6caec8ece7729beb3876ea4b8 (patch)
tree683d8b3b14c5d458ca06d50dac7468cbc40e4c02 /django/db
parent1f11069aa59df03157ed90788c7759df77ec4377 (diff)
Made the caching of related and reverse related objects consistent in OneToOneFields. Fixed #13839. Refs #17439.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17890 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db')
-rw-r--r--django/db/models/fields/related.py55
1 files changed, 32 insertions, 23 deletions
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 7034d34867..fbb40d9175 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -249,11 +249,19 @@ class SingleRelatedObjectDescriptor(object):
if instance is None:
return self
try:
- return getattr(instance, self.cache_name)
+ rel_obj = getattr(instance, self.cache_name)
except AttributeError:
params = {'%s__pk' % self.related.field.name: instance._get_pk_val()}
- rel_obj = self.get_query_set(instance=instance).get(**params)
+ try:
+ rel_obj = self.get_query_set(instance=instance).get(**params)
+ except self.related.model.DoesNotExist:
+ rel_obj = None
+ else:
+ setattr(rel_obj, self.related.field.get_cache_name(), instance)
setattr(instance, self.cache_name, rel_obj)
+ if rel_obj is None:
+ raise self.related.model.DoesNotExist
+ else:
return rel_obj
def __set__(self, instance, value):
@@ -331,24 +339,27 @@ class ReverseSingleRelatedObjectDescriptor(object):
def __get__(self, instance, instance_type=None):
if instance is None:
return self
-
try:
- return getattr(instance, self.cache_name)
+ rel_obj = getattr(instance, self.cache_name)
except AttributeError:
val = getattr(instance, self.field.attname)
if val is None:
- # If NULL is an allowed value, return it.
- if self.field.null:
- return None
- raise self.field.rel.to.DoesNotExist
- other_field = self.field.rel.get_related_field()
- if other_field.rel:
- params = {'%s__pk' % self.field.rel.field_name: val}
+ rel_obj = None
else:
- params = {'%s__exact' % self.field.rel.field_name: val}
- qs = self.get_query_set(instance=instance)
- rel_obj = qs.get(**params)
+ other_field = self.field.rel.get_related_field()
+ if other_field.rel:
+ params = {'%s__pk' % self.field.rel.field_name: val}
+ else:
+ params = {'%s__exact' % self.field.rel.field_name: val}
+ qs = self.get_query_set(instance=instance)
+ # Assuming the database enforces foreign keys, this won't fail.
+ rel_obj = qs.get(**params)
+ if not self.field.rel.multiple:
+ setattr(rel_obj, self.field.related.get_cache_name(), instance)
setattr(instance, self.cache_name, rel_obj)
+ if rel_obj is None and not self.field.null:
+ raise self.field.rel.to.DoesNotExist
+ else:
return rel_obj
def __set__(self, instance, value):
@@ -385,17 +396,13 @@ class ReverseSingleRelatedObjectDescriptor(object):
# populated the cache, then we don't care - we're only accessing
# the object to invalidate the accessor cache, so there's no
# need to populate the cache just to expire it again.
- related = getattr(instance, self.field.get_cache_name(), None)
+ related = getattr(instance, self.cache_name, None)
# If we've got an old related object, we need to clear out its
# cache. This cache also might not exist if the related object
# hasn't been accessed yet.
- if related:
- cache_name = self.field.related.get_cache_name()
- try:
- delattr(related, cache_name)
- except AttributeError:
- pass
+ if related is not None:
+ setattr(related, self.field.related.get_cache_name(), None)
# Set the value of the related field
try:
@@ -405,9 +412,11 @@ class ReverseSingleRelatedObjectDescriptor(object):
setattr(instance, self.field.attname, val)
# Since we already know what the related object is, seed the related
- # object cache now, too. This avoids another db hit if you get the
+ # object caches now, too. This avoids another db hit if you get the
# object you just set.
- setattr(instance, self.field.get_cache_name(), value)
+ setattr(instance, self.cache_name, value)
+ if value is not None and not self.field.rel.multiple:
+ setattr(value, self.field.related.get_cache_name(), instance)
class ForeignRelatedObjectsDescriptor(object):
# This class provides the functionality that makes the related-object