PageRenderTime 105ms CodeModel.GetById 20ms app.highlight 68ms RepoModel.GetById 12ms app.codeStats 0ms

/tests/modeltests/many_to_many/tests.py

https://code.google.com/p/mango-py/
Python | 384 lines | 327 code | 25 blank | 32 comment | 0 complexity | f19bce26e2b680d4a9bbd3b49ef26010 MD5 | raw file
  1from django.test import TestCase
  2from models import Article, Publication
  3
  4class ManyToManyTests(TestCase):
  5
  6    def setUp(self):
  7        # Create a couple of Publications.
  8        self.p1 = Publication.objects.create(id=None, title='The Python Journal')
  9        self.p2 = Publication.objects.create(id=None, title='Science News')
 10        self.p3 = Publication.objects.create(id=None, title='Science Weekly')
 11        self.p4 = Publication.objects.create(title='Highlights for Children')
 12
 13        self.a1 = Article.objects.create(id=None, headline='Django lets you build Web apps easily')
 14        self.a1.publications.add(self.p1)
 15
 16        self.a2 = Article.objects.create(id=None, headline='NASA uses Python')
 17        self.a2.publications.add(self.p1, self.p2, self.p3, self.p4)
 18
 19        self.a3 = Article.objects.create(headline='NASA finds intelligent life on Earth')
 20        self.a3.publications.add(self.p2)
 21
 22        self.a4 = Article.objects.create(headline='Oxygen-free diet works wonders')
 23        self.a4.publications.add(self.p2)
 24
 25    def test_add(self):
 26        # Create an Article.
 27        a5 = Article(id=None, headline='Django lets you reate Web apps easily')
 28        # You can't associate it with a Publication until it's been saved.
 29        self.assertRaises(ValueError, getattr, a5, 'publications')
 30        # Save it!
 31        a5.save()
 32        # Associate the Article with a Publication.
 33        a5.publications.add(self.p1)
 34        self.assertQuerysetEqual(a5.publications.all(),
 35                                 ['<Publication: The Python Journal>'])
 36        # Create another Article, and set it to appear in both Publications.
 37        a6 = Article(id=None, headline='ESA uses Python')
 38        a6.save()
 39        a6.publications.add(self.p1, self.p2)
 40        a6.publications.add(self.p3)
 41        # Adding a second time is OK
 42        a6.publications.add(self.p3)
 43        self.assertQuerysetEqual(a6.publications.all(),
 44            [
 45                '<Publication: Science News>',
 46                '<Publication: Science Weekly>',
 47                '<Publication: The Python Journal>',
 48            ])
 49
 50        # Adding an object of the wrong type raises TypeError
 51        self.assertRaises(TypeError, a6.publications.add, a5)
 52        # Add a Publication directly via publications.add by using keyword arguments.
 53        p4 = a6.publications.create(title='Highlights for Adults')
 54        self.assertQuerysetEqual(a6.publications.all(),
 55            [
 56                '<Publication: Highlights for Adults>',
 57                '<Publication: Science News>',
 58                '<Publication: Science Weekly>',
 59                '<Publication: The Python Journal>',
 60            ])
 61
 62    def test_reverse_add(self):
 63        # Adding via the 'other' end of an m2m
 64        a5 = Article(headline='NASA finds intelligent life on Mars')
 65        a5.save()
 66        self.p2.article_set.add(a5)
 67        self.assertQuerysetEqual(self.p2.article_set.all(),
 68            [
 69                '<Article: NASA finds intelligent life on Earth>',
 70                '<Article: NASA finds intelligent life on Mars>',
 71                '<Article: NASA uses Python>',
 72                '<Article: Oxygen-free diet works wonders>',
 73            ])
 74        self.assertQuerysetEqual(a5.publications.all(),
 75                                 ['<Publication: Science News>'])
 76
 77        # Adding via the other end using keywords
 78        new_article = self.p2.article_set.create(headline='Carbon-free diet works wonders')
 79        self.assertQuerysetEqual(
 80            self.p2.article_set.all(),
 81            [
 82                '<Article: Carbon-free diet works wonders>',
 83                '<Article: NASA finds intelligent life on Earth>',
 84                '<Article: NASA finds intelligent life on Mars>',
 85                '<Article: NASA uses Python>',
 86                '<Article: Oxygen-free diet works wonders>',
 87            ])
 88        a6 = self.p2.article_set.all()[3]
 89        self.assertQuerysetEqual(a6.publications.all(),
 90            [
 91                '<Publication: Highlights for Children>',
 92                '<Publication: Science News>',
 93                '<Publication: Science Weekly>',
 94                '<Publication: The Python Journal>',
 95            ])
 96
 97    def test_related_sets(self):
 98        # Article objects have access to their related Publication objects.
 99        self.assertQuerysetEqual(self.a1.publications.all(),
100             ['<Publication: The Python Journal>'])
101        self.assertQuerysetEqual(self.a2.publications.all(),
102            [
103                '<Publication: Highlights for Children>',
104                '<Publication: Science News>',
105                '<Publication: Science Weekly>',
106                '<Publication: The Python Journal>',
107            ])
108        # Publication objects have access to their related Article objects.
109        self.assertQuerysetEqual(self.p2.article_set.all(),
110            [
111                '<Article: NASA finds intelligent life on Earth>',
112                '<Article: NASA uses Python>',
113                '<Article: Oxygen-free diet works wonders>',
114            ])
115        self.assertQuerysetEqual(self.p1.article_set.all(),
116            [
117                '<Article: Django lets you build Web apps easily>',
118                '<Article: NASA uses Python>',
119            ])
120        self.assertQuerysetEqual(Publication.objects.get(id=self.p4.id).article_set.all(),
121                                 ['<Article: NASA uses Python>'])
122
123    def test_selects(self):
124        # We can perform kwarg queries across m2m relationships
125        self.assertQuerysetEqual(
126            Article.objects.filter(publications__id__exact=self.p1.id),
127            [
128                '<Article: Django lets you build Web apps easily>',
129                '<Article: NASA uses Python>',
130            ])
131        self.assertQuerysetEqual(
132            Article.objects.filter(publications__pk=self.p1.id),
133            [
134                '<Article: Django lets you build Web apps easily>',
135                '<Article: NASA uses Python>',
136            ])
137        self.assertQuerysetEqual(
138            Article.objects.filter(publications=self.p1.id),
139            [
140                '<Article: Django lets you build Web apps easily>',
141                '<Article: NASA uses Python>',
142            ])
143        self.assertQuerysetEqual(
144            Article.objects.filter(publications=self.p1),
145            [
146                '<Article: Django lets you build Web apps easily>',
147                '<Article: NASA uses Python>',
148            ])
149        self.assertQuerysetEqual(
150            Article.objects.filter(publications__title__startswith="Science"),
151            [
152                '<Article: NASA finds intelligent life on Earth>',
153                '<Article: NASA uses Python>',
154                '<Article: NASA uses Python>',
155                '<Article: Oxygen-free diet works wonders>',
156            ])
157        self.assertQuerysetEqual(
158            Article.objects.filter(publications__title__startswith="Science").distinct(),
159            [
160                '<Article: NASA finds intelligent life on Earth>',
161                '<Article: NASA uses Python>',
162                '<Article: Oxygen-free diet works wonders>',
163            ])
164
165        # The count() function respects distinct() as well.
166        self.assertEqual(Article.objects.filter(publications__title__startswith="Science").count(), 4)
167        self.assertEqual(Article.objects.filter(publications__title__startswith="Science").distinct().count(), 3)
168        self.assertQuerysetEqual(
169            Article.objects.filter(publications__in=[self.p1.id,self.p2.id]).distinct(),
170            [
171                '<Article: Django lets you build Web apps easily>',
172                '<Article: NASA finds intelligent life on Earth>',
173                '<Article: NASA uses Python>',
174                '<Article: Oxygen-free diet works wonders>',
175            ])
176        self.assertQuerysetEqual(
177            Article.objects.filter(publications__in=[self.p1.id,self.p2]).distinct(),
178            [
179                '<Article: Django lets you build Web apps easily>',
180                '<Article: NASA finds intelligent life on Earth>',
181                '<Article: NASA uses Python>',
182                '<Article: Oxygen-free diet works wonders>',
183            ])
184        self.assertQuerysetEqual(
185            Article.objects.filter(publications__in=[self.p1,self.p2]).distinct(),
186            [
187                '<Article: Django lets you build Web apps easily>',
188                '<Article: NASA finds intelligent life on Earth>',
189                '<Article: NASA uses Python>',
190                '<Article: Oxygen-free diet works wonders>',
191            ])
192
193        # Excluding a related item works as you would expect, too (although the SQL
194        # involved is a little complex).
195        self.assertQuerysetEqual(Article.objects.exclude(publications=self.p2),
196                                 ['<Article: Django lets you build Web apps easily>'])
197
198    def test_reverse_selects(self):
199        # Reverse m2m queries are supported (i.e., starting at the table that
200        # doesn't have a ManyToManyField).
201        self.assertQuerysetEqual(Publication.objects.filter(id__exact=self.p1.id),
202                                 ['<Publication: The Python Journal>'])
203        self.assertQuerysetEqual(Publication.objects.filter(pk=self.p1.id),
204                                 ['<Publication: The Python Journal>'])
205        self.assertQuerysetEqual(
206            Publication.objects.filter(article__headline__startswith="NASA"),
207            [
208                '<Publication: Highlights for Children>',
209                '<Publication: Science News>',
210                '<Publication: Science News>',
211                '<Publication: Science Weekly>',
212                '<Publication: The Python Journal>',
213            ])
214        self.assertQuerysetEqual(Publication.objects.filter(article__id__exact=self.a1.id),
215                                 ['<Publication: The Python Journal>'])
216        self.assertQuerysetEqual(Publication.objects.filter(article__pk=self.a1.id),
217                                 ['<Publication: The Python Journal>'])
218        self.assertQuerysetEqual(Publication.objects.filter(article=self.a1.id),
219                                 ['<Publication: The Python Journal>'])
220        self.assertQuerysetEqual(Publication.objects.filter(article=self.a1),
221                                 ['<Publication: The Python Journal>'])
222
223        self.assertQuerysetEqual(
224            Publication.objects.filter(article__in=[self.a1.id,self.a2.id]).distinct(),
225            [
226                '<Publication: Highlights for Children>',
227                '<Publication: Science News>',
228                '<Publication: Science Weekly>',
229                '<Publication: The Python Journal>',
230            ])
231        self.assertQuerysetEqual(
232            Publication.objects.filter(article__in=[self.a1.id,self.a2]).distinct(),
233            [
234                '<Publication: Highlights for Children>',
235                '<Publication: Science News>',
236                '<Publication: Science Weekly>',
237                '<Publication: The Python Journal>',
238            ])
239        self.assertQuerysetEqual(
240            Publication.objects.filter(article__in=[self.a1,self.a2]).distinct(),
241            [
242                '<Publication: Highlights for Children>',
243                '<Publication: Science News>',
244                '<Publication: Science Weekly>',
245                '<Publication: The Python Journal>',
246            ])
247
248    def test_delete(self):
249        # If we delete a Publication, its Articles won't be able to access it.
250        self.p1.delete()
251        self.assertQuerysetEqual(Publication.objects.all(),
252            [
253                '<Publication: Highlights for Children>',
254                '<Publication: Science News>',
255                '<Publication: Science Weekly>',
256            ])
257        self.assertQuerysetEqual(self.a1.publications.all(), [])
258        # If we delete an Article, its Publications won't be able to access it.
259        self.a2.delete()
260        self.assertQuerysetEqual(Article.objects.all(),
261            [
262                '<Article: Django lets you build Web apps easily>',
263                '<Article: NASA finds intelligent life on Earth>',
264                '<Article: Oxygen-free diet works wonders>',
265            ])
266        self.assertQuerysetEqual(self.p2.article_set.all(),
267            [
268                '<Article: NASA finds intelligent life on Earth>',
269                '<Article: Oxygen-free diet works wonders>',
270            ])
271
272    def test_bulk_delete(self):
273        # Bulk delete some Publications - references to deleted publications should go
274        Publication.objects.filter(title__startswith='Science').delete()
275        self.assertQuerysetEqual(Publication.objects.all(),
276            [
277                '<Publication: Highlights for Children>',
278                '<Publication: The Python Journal>',
279            ])
280        self.assertQuerysetEqual(Article.objects.all(),
281            [
282                '<Article: Django lets you build Web apps easily>',
283                '<Article: NASA finds intelligent life on Earth>',
284                '<Article: NASA uses Python>',
285                '<Article: Oxygen-free diet works wonders>',
286            ])
287        self.assertQuerysetEqual(self.a2.publications.all(),
288            [
289                '<Publication: Highlights for Children>',
290                '<Publication: The Python Journal>',
291            ])
292
293        # Bulk delete some articles - references to deleted objects should go
294        q = Article.objects.filter(headline__startswith='Django')
295        self.assertQuerysetEqual(q, ['<Article: Django lets you build Web apps easily>'])
296        q.delete()
297        # After the delete, the QuerySet cache needs to be cleared,
298        # and the referenced objects should be gone
299        self.assertQuerysetEqual(q, [])
300        self.assertQuerysetEqual(self.p1.article_set.all(),
301                                 ['<Article: NASA uses Python>'])
302
303    def test_remove(self):
304        # Removing publication from an article:
305        self.assertQuerysetEqual(self.p2.article_set.all(),
306            [
307                '<Article: NASA finds intelligent life on Earth>',
308                '<Article: NASA uses Python>',
309                '<Article: Oxygen-free diet works wonders>',
310            ])
311        self.a4.publications.remove(self.p2)
312        self.assertQuerysetEqual(self.p2.article_set.all(),
313            [
314                '<Article: NASA finds intelligent life on Earth>',
315                '<Article: NASA uses Python>',
316            ])
317        self.assertQuerysetEqual(self.a4.publications.all(), [])
318        # And from the other end
319        self.p2.article_set.remove(self.a3)
320        self.assertQuerysetEqual(self.p2.article_set.all(),
321            [
322                '<Article: NASA uses Python>',
323            ])
324        self.assertQuerysetEqual(self.a3.publications.all(), [])
325
326    def test_assign(self):
327        # Relation sets can be assigned. Assignment clears any existing set members
328        self.p2.article_set = [self.a4, self.a3]
329        self.assertQuerysetEqual(self.p2.article_set.all(),
330            [
331                '<Article: NASA finds intelligent life on Earth>',
332                '<Article: Oxygen-free diet works wonders>',
333            ])
334        self.assertQuerysetEqual(self.a4.publications.all(),
335                                 ['<Publication: Science News>'])
336        self.a4.publications = [self.p3.id]
337        self.assertQuerysetEqual(self.p2.article_set.all(),
338                                 ['<Article: NASA finds intelligent life on Earth>'])
339        self.assertQuerysetEqual(self.a4.publications.all(),
340                                 ['<Publication: Science Weekly>'])
341
342        # An alternate to calling clear() is to assign the empty set
343        self.p2.article_set = []
344        self.assertQuerysetEqual(self.p2.article_set.all(), [])
345        self.a4.publications = []
346        self.assertQuerysetEqual(self.a4.publications.all(), [])
347
348    def test_assign_ids(self):
349        # Relation sets can also be set using primary key values
350        self.p2.article_set = [self.a4.id, self.a3.id]
351        self.assertQuerysetEqual(self.p2.article_set.all(),
352            [
353                '<Article: NASA finds intelligent life on Earth>',
354                '<Article: Oxygen-free diet works wonders>',
355            ])
356        self.assertQuerysetEqual(self.a4.publications.all(),
357                                 ['<Publication: Science News>'])
358        self.a4.publications = [self.p3.id]
359        self.assertQuerysetEqual(self.p2.article_set.all(),
360                                 ['<Article: NASA finds intelligent life on Earth>'])
361        self.assertQuerysetEqual(self.a4.publications.all(),
362                                 ['<Publication: Science Weekly>'])
363
364    def test_clear(self):
365        # Relation sets can be cleared:
366        self.p2.article_set.clear()
367        self.assertQuerysetEqual(self.p2.article_set.all(), [])
368        self.assertQuerysetEqual(self.a4.publications.all(), [])
369
370        # And you can clear from the other end
371        self.p2.article_set.add(self.a3, self.a4)
372        self.assertQuerysetEqual(self.p2.article_set.all(),
373            [
374                '<Article: NASA finds intelligent life on Earth>',
375                '<Article: Oxygen-free diet works wonders>',
376            ])
377        self.assertQuerysetEqual(self.a4.publications.all(),
378            [
379                '<Publication: Science News>',
380            ])
381        self.a4.publications.clear()
382        self.assertQuerysetEqual(self.a4.publications.all(), [])
383        self.assertQuerysetEqual(self.p2.article_set.all(),
384                                 ['<Article: NASA finds intelligent life on Earth>'])