From f64c581497b6816e3219bb5fcee8c8835ad704ce Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 28 Feb 2006 11:36:20 +0000 Subject: [PATCH] magic-removal: Fixed #1407 -- Added a __set__ method for the single object descriptor. This enables setting related objects using poll.choice = c, and ensures that the cache is kept accurate in the process. git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2435 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/fields/related.py | 19 +++++++++++++++---- tests/modeltests/many_to_one/models.py | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index e93777a368..c7ae1a7ccd 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -104,6 +104,17 @@ class SingleRelatedObjectDescriptor(object): setattr(instance, cache_name, rel_obj) return rel_obj + def __set__(self, instance, value): + # Set the value of the related field + if value: + val = getattr(value, self._field.rel.get_related_field().attname) + else: + val = None + setattr(instance, self._field.attname, val) + + # Set the cache to point to the new object + setattr(instance, self._field.get_cache_name(), value) + class ForeignRelatedObjectsDescriptor(object): # This class provides the functionality that makes the related-object # managers available as attributes on a model class, for fields that have @@ -130,8 +141,7 @@ class ForeignRelatedObjectsDescriptor(object): def add(self, *objs): for obj in objs: - val = getattr(instance, rel_field.rel.get_related_field().attname) - setattr(obj, rel_field.attname, val) + setattr(obj, rel_field.name, instance) obj.save() add.alters_data = True @@ -146,8 +156,9 @@ class ForeignRelatedObjectsDescriptor(object): def remove(self, *objs): val = getattr(instance, rel_field.rel.get_related_field().attname) for obj in objs: + # Is obj actually part of this descriptor set? if getattr(obj, rel_field.attname) == val: - setattr(obj, rel_field.attname, None) + setattr(obj, rel_field.name, None) obj.save() else: raise rel_field.rel.to.DoesNotExist, "'%s' is not related to '%s'." % (obj, instance) @@ -155,7 +166,7 @@ class ForeignRelatedObjectsDescriptor(object): def clear(self): for obj in self.all(): - setattr(obj, rel_field.attname, None) + setattr(obj, rel_field.name, None) obj.save() add.alters_data = True diff --git a/tests/modeltests/many_to_one/models.py b/tests/modeltests/many_to_one/models.py index 4e765f29b0..6f1ac96359 100644 --- a/tests/modeltests/many_to_one/models.py +++ b/tests/modeltests/many_to_one/models.py @@ -71,6 +71,22 @@ John's second story >>> r2.article_set.all() [Paul's story] +# Assign the article to the reporter directly using the descriptor +>>> new_article2.reporter = r +>>> new_article2.save() +>>> new_article2.reporter +John Smith +>>> new_article2.reporter.id +1 +>>> r.article_set.all() +[This is a test, John's second story, Paul's story] +>>> r2.article_set.all() +[] + +# Set the article back again. +>>> new_article2.reporter = r2 +>>> new_article2.save() + # Reporter cannot be null - there should not be a clear or remove method >>> hasattr(r2.article_set, 'remove') False