thirdparty/google_appengine/lib/django/tests/modeltests/many_to_many/models.py
changeset 2866 a04b1e4126c4
parent 2864 2e0b0af889be
child 2868 9f7f269383f7
equal deleted inserted replaced
2864:2e0b0af889be 2866:a04b1e4126c4
     1 """
       
     2 5. Many-to-many relationships
       
     3 
       
     4 To define a many-to-many relationship, use ManyToManyField().
       
     5 
       
     6 In this example, an article can be published in multiple publications,
       
     7 and a publication has multiple articles.
       
     8 """
       
     9 
       
    10 from django.db import models
       
    11 
       
    12 class Publication(models.Model):
       
    13     title = models.CharField(maxlength=30)
       
    14 
       
    15     def __str__(self):
       
    16         return self.title
       
    17 
       
    18     class Meta:
       
    19         ordering = ('title',)
       
    20 
       
    21 class Article(models.Model):
       
    22     headline = models.CharField(maxlength=100)
       
    23     publications = models.ManyToManyField(Publication)
       
    24 
       
    25     def __str__(self):
       
    26         return self.headline
       
    27 
       
    28     class Meta:
       
    29         ordering = ('headline',)
       
    30 
       
    31 __test__ = {'API_TESTS':"""
       
    32 # Create a couple of Publications.
       
    33 >>> p1 = Publication(id=None, title='The Python Journal')
       
    34 >>> p1.save()
       
    35 >>> p2 = Publication(id=None, title='Science News')
       
    36 >>> p2.save()
       
    37 >>> p3 = Publication(id=None, title='Science Weekly')
       
    38 >>> p3.save()
       
    39 
       
    40 # Create an Article.
       
    41 >>> a1 = Article(id=None, headline='Django lets you build Web apps easily')
       
    42 >>> a1.save()
       
    43 
       
    44 # Associate the Article with a Publication.
       
    45 >>> a1.publications.add(p1)
       
    46 
       
    47 # Create another Article, and set it to appear in both Publications.
       
    48 >>> a2 = Article(id=None, headline='NASA uses Python')
       
    49 >>> a2.save()
       
    50 >>> a2.publications.add(p1, p2)
       
    51 >>> a2.publications.add(p3)
       
    52 
       
    53 # Adding a second time is OK
       
    54 >>> a2.publications.add(p3)
       
    55 
       
    56 # Add a Publication directly via publications.add by using keyword arguments.
       
    57 >>> new_publication = a2.publications.create(title='Highlights for Children')
       
    58 
       
    59 # Article objects have access to their related Publication objects.
       
    60 >>> a1.publications.all()
       
    61 [<Publication: The Python Journal>]
       
    62 >>> a2.publications.all()
       
    63 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
       
    64 
       
    65 # Publication objects have access to their related Article objects.
       
    66 >>> p2.article_set.all()
       
    67 [<Article: NASA uses Python>]
       
    68 >>> p1.article_set.all()
       
    69 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
    70 >>> Publication.objects.get(id=4).article_set.all()
       
    71 [<Article: NASA uses Python>]
       
    72 
       
    73 # We can perform kwarg queries across m2m relationships
       
    74 >>> Article.objects.filter(publications__id__exact=1)
       
    75 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
    76 >>> Article.objects.filter(publications__pk=1)
       
    77 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
    78 >>> Article.objects.filter(publications=1)
       
    79 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
    80 >>> Article.objects.filter(publications=p1)
       
    81 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
    82 
       
    83 >>> Article.objects.filter(publications__title__startswith="Science")
       
    84 [<Article: NASA uses Python>, <Article: NASA uses Python>]
       
    85 
       
    86 >>> Article.objects.filter(publications__title__startswith="Science").distinct()
       
    87 [<Article: NASA uses Python>]
       
    88 
       
    89 # The count() function respects distinct() as well.
       
    90 >>> Article.objects.filter(publications__title__startswith="Science").count()
       
    91 2
       
    92 
       
    93 >>> Article.objects.filter(publications__title__startswith="Science").distinct().count()
       
    94 1
       
    95 
       
    96 >>> Article.objects.filter(publications__in=[1,2]).distinct()
       
    97 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
    98 >>> Article.objects.filter(publications__in=[1,p2]).distinct()
       
    99 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
   100 >>> Article.objects.filter(publications__in=[p1,p2]).distinct()
       
   101 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
       
   102 
       
   103 # Reverse m2m queries are supported (i.e., starting at the table that doesn't
       
   104 # have a ManyToManyField).
       
   105 >>> Publication.objects.filter(id__exact=1)
       
   106 [<Publication: The Python Journal>]
       
   107 >>> Publication.objects.filter(pk=1)
       
   108 [<Publication: The Python Journal>]
       
   109 
       
   110 >>> Publication.objects.filter(article__headline__startswith="NASA")
       
   111 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
       
   112 
       
   113 >>> Publication.objects.filter(article__id__exact=1)
       
   114 [<Publication: The Python Journal>]
       
   115 >>> Publication.objects.filter(article__pk=1)
       
   116 [<Publication: The Python Journal>]
       
   117 >>> Publication.objects.filter(article=1)
       
   118 [<Publication: The Python Journal>]
       
   119 >>> Publication.objects.filter(article=a1)
       
   120 [<Publication: The Python Journal>]
       
   121 
       
   122 >>> Publication.objects.filter(article__in=[1,2]).distinct()
       
   123 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
       
   124 >>> Publication.objects.filter(article__in=[1,a2]).distinct()
       
   125 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
       
   126 >>> Publication.objects.filter(article__in=[a1,a2]).distinct()
       
   127 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
       
   128 
       
   129 # If we delete a Publication, its Articles won't be able to access it.
       
   130 >>> p1.delete()
       
   131 >>> Publication.objects.all()
       
   132 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]
       
   133 >>> a1 = Article.objects.get(pk=1)
       
   134 >>> a1.publications.all()
       
   135 []
       
   136 
       
   137 # If we delete an Article, its Publications won't be able to access it.
       
   138 >>> a2.delete()
       
   139 >>> Article.objects.all()
       
   140 [<Article: Django lets you build Web apps easily>]
       
   141 >>> p2.article_set.all()
       
   142 []
       
   143 
       
   144 # Adding via the 'other' end of an m2m
       
   145 >>> a4 = Article(headline='NASA finds intelligent life on Earth')
       
   146 >>> a4.save()
       
   147 >>> p2.article_set.add(a4)
       
   148 >>> p2.article_set.all()
       
   149 [<Article: NASA finds intelligent life on Earth>]
       
   150 >>> a4.publications.all()
       
   151 [<Publication: Science News>]
       
   152 
       
   153 # Adding via the other end using keywords
       
   154 >>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
       
   155 >>> p2.article_set.all()
       
   156 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
       
   157 >>> a5 = p2.article_set.all()[1]
       
   158 >>> a5.publications.all()
       
   159 [<Publication: Science News>]
       
   160 
       
   161 # Removing publication from an article:
       
   162 >>> a4.publications.remove(p2)
       
   163 >>> p2.article_set.all()
       
   164 [<Article: Oxygen-free diet works wonders>]
       
   165 >>> a4.publications.all()
       
   166 []
       
   167 
       
   168 # And from the other end
       
   169 >>> p2.article_set.remove(a5)
       
   170 >>> p2.article_set.all()
       
   171 []
       
   172 >>> a5.publications.all()
       
   173 []
       
   174 
       
   175 # Relation sets can be assigned. Assignment clears any existing set members
       
   176 >>> p2.article_set = [a4, a5]
       
   177 >>> p2.article_set.all()
       
   178 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
       
   179 >>> a4.publications.all()
       
   180 [<Publication: Science News>]
       
   181 >>> a4.publications = [p3]
       
   182 >>> p2.article_set.all()
       
   183 [<Article: Oxygen-free diet works wonders>]
       
   184 >>> a4.publications.all()
       
   185 [<Publication: Science Weekly>]
       
   186 
       
   187 # Relation sets can be cleared:
       
   188 >>> p2.article_set.clear()
       
   189 >>> p2.article_set.all()
       
   190 []
       
   191 >>> a4.publications.all()
       
   192 [<Publication: Science Weekly>]
       
   193 
       
   194 # And you can clear from the other end
       
   195 >>> p2.article_set.add(a4, a5)
       
   196 >>> p2.article_set.all()
       
   197 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
       
   198 >>> a4.publications.all()
       
   199 [<Publication: Science News>, <Publication: Science Weekly>]
       
   200 >>> a4.publications.clear()
       
   201 >>> a4.publications.all()
       
   202 []
       
   203 >>> p2.article_set.all()
       
   204 [<Article: Oxygen-free diet works wonders>]
       
   205 
       
   206 # Relation sets can also be set using primary key values
       
   207 >>> p2.article_set = [a4.id, a5.id]
       
   208 >>> p2.article_set.all()
       
   209 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
       
   210 >>> a4.publications.all()
       
   211 [<Publication: Science News>]
       
   212 >>> a4.publications = [p3.id]
       
   213 >>> p2.article_set.all()
       
   214 [<Article: Oxygen-free diet works wonders>]
       
   215 >>> a4.publications.all()
       
   216 [<Publication: Science Weekly>]
       
   217 
       
   218 # Recreate the article and Publication we have deleted.
       
   219 >>> p1 = Publication(id=None, title='The Python Journal')
       
   220 >>> p1.save()
       
   221 >>> a2 = Article(id=None, headline='NASA uses Python')
       
   222 >>> a2.save()
       
   223 >>> a2.publications.add(p1, p2, p3)
       
   224 
       
   225 # Bulk delete some Publications - references to deleted publications should go
       
   226 >>> Publication.objects.filter(title__startswith='Science').delete()
       
   227 >>> Publication.objects.all()
       
   228 [<Publication: Highlights for Children>, <Publication: The Python Journal>]
       
   229 >>> Article.objects.all()
       
   230 [<Article: Django lets you build Web apps easily>, <Article: NASA finds intelligent life on Earth>, <Article: NASA uses Python>, <Article: Oxygen-free diet works wonders>]
       
   231 >>> a2.publications.all()
       
   232 [<Publication: The Python Journal>]
       
   233 
       
   234 # Bulk delete some articles - references to deleted objects should go
       
   235 >>> q = Article.objects.filter(headline__startswith='Django')
       
   236 >>> print q
       
   237 [<Article: Django lets you build Web apps easily>]
       
   238 >>> q.delete()
       
   239 
       
   240 # After the delete, the QuerySet cache needs to be cleared, and the referenced objects should be gone
       
   241 >>> print q
       
   242 []
       
   243 >>> p1.article_set.all()
       
   244 [<Article: NASA uses Python>]
       
   245 
       
   246 # An alternate to calling clear() is to assign the empty set
       
   247 >>> p1.article_set = []
       
   248 >>> p1.article_set.all()
       
   249 []
       
   250 
       
   251 >>> a2.publications = [p1, new_publication]
       
   252 >>> a2.publications.all()
       
   253 [<Publication: Highlights for Children>, <Publication: The Python Journal>]
       
   254 >>> a2.publications = []
       
   255 >>> a2.publications.all()
       
   256 []
       
   257 
       
   258 """}