magic-removal: Refs #1407 -- Added remove() and clear() methods for ForeignKeys that allow nulls.
git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2434 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f9ed0eded9
commit
a6a6c4117b
|
@ -141,6 +141,24 @@ class ForeignRelatedObjectsDescriptor(object):
|
||||||
return new_obj
|
return new_obj
|
||||||
create.alters_data = True
|
create.alters_data = True
|
||||||
|
|
||||||
|
# remove() and clear() are only provided if the ForeignKey can have a value of null.
|
||||||
|
if rel_field.null:
|
||||||
|
def remove(self, *objs):
|
||||||
|
val = getattr(instance, rel_field.rel.get_related_field().attname)
|
||||||
|
for obj in objs:
|
||||||
|
if getattr(obj, rel_field.attname) == val:
|
||||||
|
setattr(obj, rel_field.attname, None)
|
||||||
|
obj.save()
|
||||||
|
else:
|
||||||
|
raise rel_field.rel.to.DoesNotExist, "'%s' is not related to '%s'." % (obj, instance)
|
||||||
|
add.alters_data = True
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
for obj in self.all():
|
||||||
|
setattr(obj, rel_field.attname, None)
|
||||||
|
obj.save()
|
||||||
|
add.alters_data = True
|
||||||
|
|
||||||
manager = RelatedManager()
|
manager = RelatedManager()
|
||||||
manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
|
manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
|
||||||
manager.model = self.related.model
|
manager.model = self.related.model
|
||||||
|
|
|
@ -71,6 +71,12 @@ John's second story
|
||||||
>>> r2.article_set.all()
|
>>> r2.article_set.all()
|
||||||
[Paul's story]
|
[Paul's story]
|
||||||
|
|
||||||
|
# Reporter cannot be null - there should not be a clear or remove method
|
||||||
|
>>> hasattr(r2.article_set, 'remove')
|
||||||
|
False
|
||||||
|
>>> hasattr(r2.article_set, 'clear')
|
||||||
|
False
|
||||||
|
|
||||||
# Reporter objects have access to their related Article objects.
|
# Reporter objects have access to their related Article objects.
|
||||||
>>> r.article_set.order_by('pub_date')
|
>>> r.article_set.order_by('pub_date')
|
||||||
[This is a test, John's second story]
|
[This is a test, John's second story]
|
||||||
|
|
|
@ -20,6 +20,9 @@ class Article(models.Model):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ('headline',)
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
# Create a Reporter.
|
# Create a Reporter.
|
||||||
>>> r = Reporter(name='John Smith')
|
>>> r = Reporter(name='John Smith')
|
||||||
|
@ -79,4 +82,40 @@ DoesNotExist
|
||||||
# To retrieve the articles with no reporters set, use "reporter__isnull=True".
|
# To retrieve the articles with no reporters set, use "reporter__isnull=True".
|
||||||
>>> Article.objects.filter(reporter__isnull=True)
|
>>> Article.objects.filter(reporter__isnull=True)
|
||||||
[Third]
|
[Third]
|
||||||
|
|
||||||
|
# Set the reporter for the Third article
|
||||||
|
>>> r.article_set.add(a3)
|
||||||
|
>>> r.article_set.all()
|
||||||
|
[First, Second, Third]
|
||||||
|
|
||||||
|
# Remove an article from the set, and check that it was removed.
|
||||||
|
>>> r.article_set.remove(a3)
|
||||||
|
>>> r.article_set.all()
|
||||||
|
[First, Second]
|
||||||
|
>>> Article.objects.filter(reporter__isnull=True)
|
||||||
|
[Third]
|
||||||
|
|
||||||
|
# Create another article and reporter
|
||||||
|
>>> r2 = Reporter(name='Paul Jones')
|
||||||
|
>>> r2.save()
|
||||||
|
>>> a4 = r2.article_set.create(headline='Fourth')
|
||||||
|
>>> r2.article_set.all()
|
||||||
|
[Fourth]
|
||||||
|
|
||||||
|
# Try to remove a4 from a set it does not belong to
|
||||||
|
>>> r.article_set.remove(a4)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
DoesNotExist: 'Fourth' is not related to 'John Smith'.
|
||||||
|
|
||||||
|
>>> r2.article_set.all()
|
||||||
|
[Fourth]
|
||||||
|
|
||||||
|
# Clear the rest of the set
|
||||||
|
>>> r.article_set.clear()
|
||||||
|
>>> r.article_set.all()
|
||||||
|
[]
|
||||||
|
>>> Article.objects.filter(reporter__isnull=True)
|
||||||
|
[First, Second, Third]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue