1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

magic-removal: Added descriptor code for assignment of related object sets (Reporter.article_set = [a,b,c]).

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2510 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2006-03-12 03:58:11 +00:00
parent 9460c54e22
commit a5bd0543f1
4 changed files with 68 additions and 11 deletions

View File

@ -94,6 +94,8 @@ class SingleRelatedObjectDescriptor(object):
return rel_obj
def __set__(self, instance, value):
if instance is None:
raise AttributeError, "%s must be accessed via instance" % self.related.opts.object_name
# Set the value of the related field
setattr(value, self.related.field.attname, instance)
@ -126,6 +128,8 @@ class ReverseSingleRelatedObjectDescriptor(object):
return rel_obj
def __set__(self, instance, value):
if instance is None:
raise AttributeError, "%s must be accessed via instance" % self._field.name
# Set the value of the related field
try:
val = getattr(value, self.field.rel.get_related_field().attname)
@ -197,6 +201,18 @@ class ForeignRelatedObjectsDescriptor(object):
return manager
def __set__(self, instance, value):
if instance is None:
raise AttributeError, "Manager must be accessed via instance"
manager = self.__get__(instance)
# If the foreign key can support nulls, then completely clear the related set.
# Otherwise, just move the named objects into the set.
if self.related.field.null:
manager.clear()
for obj in value:
manager.add(obj)
def _add_m2m_items(rel_manager_inst, managerclass, rel_model, join_table, source_col_name,
target_col_name, source_pk_val, *objs):
# Utility function used by the ManyRelatedObjectsDescriptors
@ -329,6 +345,15 @@ class ManyRelatedObjectsDescriptor(object):
return manager
def __set__(self, instance, value):
if instance is None:
raise AttributeError, "Manager must be accessed via instance"
manager = self.__get__(instance)
manager.clear()
for obj in value:
manager.add(obj)
class ReverseManyRelatedObjectsDescriptor(object):
# This class provides the functionality that makes the related-object
# managers available as attributes on a model class, for fields that have
@ -401,6 +426,15 @@ class ReverseManyRelatedObjectsDescriptor(object):
return manager
def __set__(self, instance, value):
if instance is None:
raise AttributeError, "Manager must be accessed via instance"
manager = self.__get__(instance)
manager.clear()
for obj in value:
manager.add(obj)
class ForeignKey(RelatedField, Field):
empty_strings_allowed = False
def __init__(self, to, to_field=None, **kwargs):

View File

@ -144,12 +144,19 @@ API_TESTS = """
>>> a5.publications.all()
[]
# You can clear the whole lot:
# (put some back first)
>>> p2.article_set.add(a4, a5)
>>> a4.publications.add(p3)
# Relation sets can be assigned. Assignment clears any existing set members
>>> p2.article_set = [a4, a5]
>>> p2.article_set.all()
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
>>> a4.publications.all()
[Science News, Science Weekly]
[Science News]
>>> a4.publications = [p3]
>>> p2.article_set.all()
[Oxygen-free diet works wonders]
>>> a4.publications.all()
[Science Weekly]
# Relation sets can be cleared:
>>> p2.article_set.clear()
>>> p2.article_set.all()
[]
@ -196,5 +203,4 @@ API_TESTS = """
>>> p1.article_set.all()
[NASA uses Python]
"""

View File

@ -83,9 +83,20 @@ John Smith
>>> r2.article_set.all()
[]
# Set the article back again.
>>> new_article2.reporter = r2
>>> new_article2.save()
# Set the article back again using set descriptor.
>>> r2.article_set = [new_article, new_article2]
>>> r.article_set.all()
[This is a test]
>>> r2.article_set.all()
[John's second story, Paul's story]
# Funny case - assignment notation can only go so far; because the
# ForeignKey cannot be null, existing members of the set must remain
>>> r.article_set = [new_article]
>>> r.article_set.all()
[This is a test, John's second story]
>>> r2.article_set.all()
[Paul's story]
# Reporter cannot be null - there should not be a clear or remove method
>>> hasattr(r2.article_set, 'remove')

View File

@ -49,7 +49,7 @@ Second
1
# Reporter objects have access to their related Article objects.
>>> r.article_set.order_by('headline')
>>> r.article_set.all()
[First, Second]
>>> r.article_set.filter(headline__startswith='Fir')
[First]
@ -111,11 +111,17 @@ DoesNotExist: 'Fourth' is not related to 'John Smith'.
>>> r2.article_set.all()
[Fourth]
# Use descriptor assignment to allocate ForeignKey. Null is legal, so
# existing members of set that are not in the assignment set are set null
>>> r2.article_set = [a2, a3]
>>> r2.article_set.all()
[Second, Third]
# Clear the rest of the set
>>> r.article_set.clear()
>>> r.article_set.all()
[]
>>> Article.objects.filter(reporter__isnull=True)
[First, Second, Third]
[First, Fourth]
"""