2
16. Many-to-one relationships that can be null
4
To define a many-to-one relationship that can have a null foreign key, use
5
``ForeignKey()`` with ``null=True`` .
8
from django.db import models
10
class Reporter(models.Model):
11
name = models.CharField(max_length=30)
13
def __unicode__(self):
16
class Article(models.Model):
17
headline = models.CharField(max_length=100)
18
reporter = models.ForeignKey(Reporter, null=True)
21
ordering = ('headline',)
23
def __unicode__(self):
26
__test__ = {'API_TESTS':"""
28
>>> r = Reporter(name='John Smith')
32
>>> a = Article(headline="First", reporter=r)
39
<Reporter: John Smith>
41
# Article objects have access to their related Reporter objects.
44
# Create an Article via the Reporter object.
45
>>> a2 = r.article_set.create(headline="Second")
51
# Reporter objects have access to their related Article objects.
52
>>> r.article_set.all()
53
[<Article: First>, <Article: Second>]
54
>>> r.article_set.filter(headline__startswith='Fir')
56
>>> r.article_set.count()
59
# Create an Article with no Reporter by passing "reporter=None".
60
>>> a3 = Article(headline="Third", reporter=None)
67
# Need to reget a3 to refresh the cache
68
>>> a3 = Article.objects.get(pk=3)
69
>>> print a3.reporter.id
70
Traceback (most recent call last):
72
AttributeError: 'NoneType' object has no attribute 'id'
74
# Accessing an article's 'reporter' attribute returns None
75
# if the reporter is set to None.
79
# To retrieve the articles with no reporters set, use "reporter__isnull=True".
80
>>> Article.objects.filter(reporter__isnull=True)
83
# We can achieve the same thing by filtering for the case where the reporter is
85
>>> Article.objects.filter(reporter=None)
88
# Set the reporter for the Third article
89
>>> r.article_set.add(a3)
90
>>> r.article_set.all()
91
[<Article: First>, <Article: Second>, <Article: Third>]
93
# Remove an article from the set, and check that it was removed.
94
>>> r.article_set.remove(a3)
95
>>> r.article_set.all()
96
[<Article: First>, <Article: Second>]
97
>>> Article.objects.filter(reporter__isnull=True)
100
# Create another article and reporter
101
>>> r2 = Reporter(name='Paul Jones')
103
>>> a4 = r2.article_set.create(headline='Fourth')
104
>>> r2.article_set.all()
107
# Try to remove a4 from a set it does not belong to
108
>>> r.article_set.remove(a4)
109
Traceback (most recent call last):
111
DoesNotExist: <Article: Fourth> is not related to <Reporter: John Smith>.
113
>>> r2.article_set.all()
116
# Use descriptor assignment to allocate ForeignKey. Null is legal, so
117
# existing members of set that are not in the assignment set are set null
118
>>> r2.article_set = [a2, a3]
119
>>> r2.article_set.all()
120
[<Article: Second>, <Article: Third>]
122
# Clear the rest of the set
123
>>> r.article_set.clear()
124
>>> r.article_set.all()
126
>>> Article.objects.filter(reporter__isnull=True)
127
[<Article: First>, <Article: Fourth>]