Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

magic-removal: Fixed #1407 -- Added a __set__ method for the single o…

…bject 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
  • Loading branch information...
commit f64c581497b6816e3219bb5fcee8c8835ad704ce 1 parent a6a6c41
@freakboy3742 freakboy3742 authored
View
19 django/db/models/fields/related.py
@@ -104,6 +104,17 @@ def __get__(self, instance, instance_type=None):
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 @@ def get_query_set(self):
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 @@ def create(self, **kwargs):
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 @@ def remove(self, *objs):
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
View
16 tests/modeltests/many_to_one/models.py
@@ -71,6 +71,22 @@ def __repr__(self):
>>> 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
Please sign in to comment.
Something went wrong with that request. Please try again.