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:
parent
9460c54e22
commit
a5bd0543f1
@ -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):
|
||||
|
@ -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]
|
||||
|
||||
|
||||
"""
|
||||
|
@ -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')
|
||||
|
@ -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]
|
||||
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user