thirdparty/google_appengine/lib/django/tests/modeltests/many_to_one/models.py
changeset 2866 a04b1e4126c4
parent 2864 2e0b0af889be
child 2868 9f7f269383f7
equal deleted inserted replaced
2864:2e0b0af889be 2866:a04b1e4126c4
     1 """
       
     2 4. Many-to-one relationships
       
     3 
       
     4 To define a many-to-one relationship, use ``ForeignKey()`` .
       
     5 """
       
     6 
       
     7 from django.db import models
       
     8 
       
     9 class Reporter(models.Model):
       
    10     first_name = models.CharField(maxlength=30)
       
    11     last_name = models.CharField(maxlength=30)
       
    12     email = models.EmailField()
       
    13 
       
    14     def __str__(self):
       
    15         return "%s %s" % (self.first_name, self.last_name)
       
    16 
       
    17 class Article(models.Model):
       
    18     headline = models.CharField(maxlength=100)
       
    19     pub_date = models.DateField()
       
    20     reporter = models.ForeignKey(Reporter)
       
    21 
       
    22     def __str__(self):
       
    23         return self.headline
       
    24 
       
    25     class Meta:
       
    26         ordering = ('headline',)
       
    27 
       
    28 __test__ = {'API_TESTS':"""
       
    29 # Create a few Reporters.
       
    30 >>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
       
    31 >>> r.save()
       
    32 
       
    33 >>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
       
    34 >>> r2.save()
       
    35 
       
    36 # Create an Article.
       
    37 >>> from datetime import datetime
       
    38 >>> a = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter=r)
       
    39 >>> a.save()
       
    40 
       
    41 >>> a.reporter.id
       
    42 1
       
    43 
       
    44 >>> a.reporter
       
    45 <Reporter: John Smith>
       
    46 
       
    47 # Article objects have access to their related Reporter objects.
       
    48 >>> r = a.reporter
       
    49 >>> r.first_name, r.last_name
       
    50 ('John', 'Smith')
       
    51 
       
    52 # Create an Article via the Reporter object.
       
    53 >>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(2005, 7, 29))
       
    54 >>> new_article
       
    55 <Article: John's second story>
       
    56 >>> new_article.reporter.id
       
    57 1
       
    58 
       
    59 # Create a new article, and add it to the article set.
       
    60 >>> new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17))
       
    61 >>> r.article_set.add(new_article2)
       
    62 >>> new_article2.reporter.id
       
    63 1
       
    64 >>> r.article_set.all()
       
    65 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
       
    66 
       
    67 # Add the same article to a different article set - check that it moves.
       
    68 >>> r2.article_set.add(new_article2)
       
    69 >>> new_article2.reporter.id
       
    70 2
       
    71 >>> r.article_set.all()
       
    72 [<Article: John's second story>, <Article: This is a test>]
       
    73 >>> r2.article_set.all()
       
    74 [<Article: Paul's story>]
       
    75 
       
    76 # Assign the article to the reporter directly using the descriptor
       
    77 >>> new_article2.reporter = r
       
    78 >>> new_article2.save()
       
    79 >>> new_article2.reporter
       
    80 <Reporter: John Smith>
       
    81 >>> new_article2.reporter.id
       
    82 1
       
    83 >>> r.article_set.all()
       
    84 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
       
    85 >>> r2.article_set.all()
       
    86 []
       
    87 
       
    88 # Set the article back again using set descriptor.
       
    89 >>> r2.article_set = [new_article, new_article2]
       
    90 >>> r.article_set.all()
       
    91 [<Article: This is a test>]
       
    92 >>> r2.article_set.all()
       
    93 [<Article: John's second story>, <Article: Paul's story>]
       
    94 
       
    95 # Funny case - assignment notation can only go so far; because the
       
    96 # ForeignKey cannot be null, existing members of the set must remain
       
    97 >>> r.article_set = [new_article]
       
    98 >>> r.article_set.all()
       
    99 [<Article: John's second story>, <Article: This is a test>]
       
   100 >>> r2.article_set.all()
       
   101 [<Article: Paul's story>]
       
   102 
       
   103 # Reporter cannot be null - there should not be a clear or remove method
       
   104 >>> hasattr(r2.article_set, 'remove')
       
   105 False
       
   106 >>> hasattr(r2.article_set, 'clear')
       
   107 False
       
   108 
       
   109 # Reporter objects have access to their related Article objects.
       
   110 >>> r.article_set.all()
       
   111 [<Article: John's second story>, <Article: This is a test>]
       
   112 
       
   113 >>> r.article_set.filter(headline__startswith='This')
       
   114 [<Article: This is a test>]
       
   115 
       
   116 >>> r.article_set.count()
       
   117 2
       
   118 
       
   119 >>> r2.article_set.count()
       
   120 1
       
   121 
       
   122 # Get articles by id
       
   123 >>> Article.objects.filter(id__exact=1)
       
   124 [<Article: This is a test>]
       
   125 >>> Article.objects.filter(pk=1)
       
   126 [<Article: This is a test>]
       
   127 
       
   128 # Query on an article property
       
   129 >>> Article.objects.filter(headline__startswith='This')
       
   130 [<Article: This is a test>]
       
   131 
       
   132 # The API automatically follows relationships as far as you need.
       
   133 # Use double underscores to separate relationships.
       
   134 # This works as many levels deep as you want. There's no limit.
       
   135 # Find all Articles for any Reporter whose first name is "John".
       
   136 >>> Article.objects.filter(reporter__first_name__exact='John')
       
   137 [<Article: John's second story>, <Article: This is a test>]
       
   138 
       
   139 # Check that implied __exact also works
       
   140 >>> Article.objects.filter(reporter__first_name='John')
       
   141 [<Article: John's second story>, <Article: This is a test>]
       
   142 
       
   143 # Query twice over the related field.
       
   144 >>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
       
   145 [<Article: John's second story>, <Article: This is a test>]
       
   146 
       
   147 # The underlying query only makes one join when a related table is referenced twice.
       
   148 >>> query = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
       
   149 >>> null, sql, null = query._get_sql_clause()
       
   150 >>> sql.count('INNER JOIN')
       
   151 1
       
   152 
       
   153 # The automatically joined table has a predictable name.
       
   154 >>> Article.objects.filter(reporter__first_name__exact='John').extra(where=["many_to_one_article__reporter.last_name='Smith'"])
       
   155 [<Article: John's second story>, <Article: This is a test>]
       
   156 
       
   157 # Find all Articles for the Reporter whose ID is 1.
       
   158 # Use direct ID check, pk check, and object comparison 
       
   159 >>> Article.objects.filter(reporter__id__exact=1)
       
   160 [<Article: John's second story>, <Article: This is a test>]
       
   161 >>> Article.objects.filter(reporter__pk=1)
       
   162 [<Article: John's second story>, <Article: This is a test>]
       
   163 >>> Article.objects.filter(reporter=1)
       
   164 [<Article: John's second story>, <Article: This is a test>]
       
   165 >>> Article.objects.filter(reporter=r)
       
   166 [<Article: John's second story>, <Article: This is a test>]
       
   167 
       
   168 >>> Article.objects.filter(reporter__in=[1,2]).distinct()
       
   169 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
       
   170 >>> Article.objects.filter(reporter__in=[r,r2]).distinct()
       
   171 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
       
   172 
       
   173 # You need two underscores between "reporter" and "id" -- not one.
       
   174 >>> Article.objects.filter(reporter_id__exact=1)
       
   175 Traceback (most recent call last):
       
   176     ...
       
   177 TypeError: Cannot resolve keyword 'reporter_id' into field
       
   178 
       
   179 # You need to specify a comparison clause
       
   180 >>> Article.objects.filter(reporter_id=1)
       
   181 Traceback (most recent call last):
       
   182     ...
       
   183 TypeError: Cannot resolve keyword 'reporter_id' into field
       
   184 
       
   185 # You can also instantiate an Article by passing
       
   186 # the Reporter's ID instead of a Reporter object.
       
   187 >>> a3 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id=r.id)
       
   188 >>> a3.save()
       
   189 >>> a3.reporter.id
       
   190 1
       
   191 >>> a3.reporter
       
   192 <Reporter: John Smith>
       
   193 
       
   194 # Similarly, the reporter ID can be a string.
       
   195 >>> a4 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id="1")
       
   196 >>> a4.save()
       
   197 >>> a4.reporter
       
   198 <Reporter: John Smith>
       
   199 
       
   200 # Reporters can be queried
       
   201 >>> Reporter.objects.filter(id__exact=1)
       
   202 [<Reporter: John Smith>]
       
   203 >>> Reporter.objects.filter(pk=1)
       
   204 [<Reporter: John Smith>]
       
   205 >>> Reporter.objects.filter(first_name__startswith='John')
       
   206 [<Reporter: John Smith>]
       
   207 
       
   208 # Reporters can query in opposite direction of ForeignKey definition
       
   209 >>> Reporter.objects.filter(article__id__exact=1)
       
   210 [<Reporter: John Smith>]
       
   211 >>> Reporter.objects.filter(article__pk=1)
       
   212 [<Reporter: John Smith>]
       
   213 >>> Reporter.objects.filter(article=1)
       
   214 [<Reporter: John Smith>]
       
   215 >>> Reporter.objects.filter(article=a)
       
   216 [<Reporter: John Smith>]
       
   217 
       
   218 >>> Reporter.objects.filter(article__in=[1,4]).distinct()
       
   219 [<Reporter: John Smith>]
       
   220 >>> Reporter.objects.filter(article__in=[1,a3]).distinct()
       
   221 [<Reporter: John Smith>]
       
   222 >>> Reporter.objects.filter(article__in=[a,a3]).distinct()
       
   223 [<Reporter: John Smith>]
       
   224 
       
   225 >>> Reporter.objects.filter(article__headline__startswith='This')
       
   226 [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
       
   227 >>> Reporter.objects.filter(article__headline__startswith='This').distinct()
       
   228 [<Reporter: John Smith>]
       
   229 
       
   230 # Counting in the opposite direction works in conjunction with distinct()
       
   231 >>> Reporter.objects.filter(article__headline__startswith='This').count()
       
   232 3
       
   233 >>> Reporter.objects.filter(article__headline__startswith='This').distinct().count()
       
   234 1
       
   235 
       
   236 # Queries can go round in circles.
       
   237 >>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
       
   238 [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
       
   239 >>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
       
   240 [<Reporter: John Smith>]
       
   241 >>> Reporter.objects.filter(article__reporter__exact=r).distinct()
       
   242 [<Reporter: John Smith>]
       
   243 
       
   244 # Check that implied __exact also works
       
   245 >>> Reporter.objects.filter(article__reporter=r).distinct()
       
   246 [<Reporter: John Smith>]
       
   247 
       
   248 # If you delete a reporter, his articles will be deleted.
       
   249 >>> Article.objects.all()
       
   250 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
       
   251 >>> Reporter.objects.order_by('first_name')
       
   252 [<Reporter: John Smith>, <Reporter: Paul Jones>]
       
   253 >>> r2.delete()
       
   254 >>> Article.objects.all()
       
   255 [<Article: John's second story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
       
   256 >>> Reporter.objects.order_by('first_name')
       
   257 [<Reporter: John Smith>]
       
   258 
       
   259 # Deletes using a join in the query
       
   260 >>> Reporter.objects.filter(article__headline__startswith='This').delete()
       
   261 >>> Reporter.objects.all()
       
   262 []
       
   263 >>> Article.objects.all()
       
   264 []
       
   265 
       
   266 """}