Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Migrated m2m_through doctests. Thanks to the anonymous contributor.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14419 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit e0a1e474b6e0edc4c400af775002bbcde305fe41 1 parent 3d96540
Russell Keith-Magee authored November 02, 2010
272  tests/modeltests/m2m_through/models.py
@@ -63,275 +63,3 @@ class Friendship(models.Model):
63 63
     first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set")
64 64
     second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set")
65 65
     date_friended = models.DateTimeField()
66  
-
67  
-__test__ = {'API_TESTS':"""
68  
->>> from datetime import datetime
69  
-
70  
-### Creation and Saving Tests ###
71  
-
72  
->>> bob = Person.objects.create(name='Bob')
73  
->>> jim = Person.objects.create(name='Jim')
74  
->>> jane = Person.objects.create(name='Jane')
75  
->>> rock = Group.objects.create(name='Rock')
76  
->>> roll = Group.objects.create(name='Roll')
77  
-
78  
-# We start out by making sure that the Group 'rock' has no members.
79  
->>> rock.members.all()
80  
-[]
81  
-
82  
-# To make Jim a member of Group Rock, simply create a Membership object.
83  
->>> m1 = Membership.objects.create(person=jim, group=rock)
84  
-
85  
-# We can do the same for Jane and Rock.
86  
->>> m2 = Membership.objects.create(person=jane, group=rock)
87  
-
88  
-# Let's check to make sure that it worked.  Jane and Jim should be members of Rock.
89  
->>> rock.members.all()
90  
-[<Person: Jane>, <Person: Jim>]
91  
-
92  
-# Now we can add a bunch more Membership objects to test with.
93  
->>> m3 = Membership.objects.create(person=bob, group=roll)
94  
->>> m4 = Membership.objects.create(person=jim, group=roll)
95  
->>> m5 = Membership.objects.create(person=jane, group=roll)
96  
-
97  
-# We can get Jim's Group membership as with any ForeignKey.
98  
->>> jim.group_set.all()
99  
-[<Group: Rock>, <Group: Roll>]
100  
-
101  
-# Querying the intermediary model works like normal.
102  
-# In this case we get Jane's membership to Rock.
103  
->>> m = Membership.objects.get(person=jane, group=rock)
104  
->>> m
105  
-<Membership: Jane is a member of Rock>
106  
-
107  
-# Now we set some date_joined dates for further testing.
108  
->>> m2.invite_reason = "She was just awesome."
109  
->>> m2.date_joined = datetime(2006, 1, 1)
110  
->>> m2.save()
111  
-
112  
->>> m5.date_joined = datetime(2004, 1, 1)
113  
->>> m5.save()
114  
-
115  
->>> m3.date_joined = datetime(2004, 1, 1)
116  
->>> m3.save()
117  
-
118  
-# It's not only get that works. Filter works like normal as well.
119  
->>> Membership.objects.filter(person=jim)
120  
-[<Membership: Jim is a member of Rock>, <Membership: Jim is a member of Roll>]
121  
-
122  
-
123  
-### Forward Descriptors Tests ###
124  
-
125  
-# Due to complications with adding via an intermediary model,
126  
-# the add method is not provided.
127  
->>> rock.members.add(bob)
128  
-Traceback (most recent call last):
129  
-...
130  
-AttributeError: 'ManyRelatedManager' object has no attribute 'add'
131  
-
132  
-# Create is also disabled as it suffers from the same problems as add.
133  
->>> rock.members.create(name='Anne')
134  
-Traceback (most recent call last):
135  
-...
136  
-AttributeError: Cannot use create() on a ManyToManyField which specifies an intermediary model. Use m2m_through.Membership's Manager instead.
137  
-
138  
-# Remove has similar complications, and is not provided either.
139  
->>> rock.members.remove(jim)
140  
-Traceback (most recent call last):
141  
-...
142  
-AttributeError: 'ManyRelatedManager' object has no attribute 'remove'
143  
-
144  
-# Here we back up the list of all members of Rock.
145  
->>> backup = list(rock.members.all())
146  
-
147  
-# ...and we verify that it has worked.
148  
->>> backup
149  
-[<Person: Jane>, <Person: Jim>]
150  
-
151  
-# The clear function should still work.
152  
->>> rock.members.clear()
153  
-
154  
-# Now there will be no members of Rock.
155  
->>> rock.members.all()
156  
-[]
157  
-
158  
-# Assignment should not work with models specifying a through model for many of
159  
-# the same reasons as adding.
160  
->>> rock.members = backup
161  
-Traceback (most recent call last):
162  
-...
163  
-AttributeError: Cannot set values on a ManyToManyField which specifies an intermediary model.  Use m2m_through.Membership's Manager instead.
164  
-
165  
-# Let's re-save those instances that we've cleared.
166  
->>> m1.save()
167  
->>> m2.save()
168  
-
169  
-# Verifying that those instances were re-saved successfully.
170  
->>> rock.members.all()
171  
-[<Person: Jane>, <Person: Jim>]
172  
-
173  
-
174  
-### Reverse Descriptors Tests ###
175  
-
176  
-# Due to complications with adding via an intermediary model,
177  
-# the add method is not provided.
178  
->>> bob.group_set.add(rock)
179  
-Traceback (most recent call last):
180  
-...
181  
-AttributeError: 'ManyRelatedManager' object has no attribute 'add'
182  
-
183  
-# Create is also disabled as it suffers from the same problems as add.
184  
->>> bob.group_set.create(name='Funk')
185  
-Traceback (most recent call last):
186  
-...
187  
-AttributeError: Cannot use create() on a ManyToManyField which specifies an intermediary model. Use m2m_through.Membership's Manager instead.
188  
-
189  
-# Remove has similar complications, and is not provided either.
190  
->>> jim.group_set.remove(rock)
191  
-Traceback (most recent call last):
192  
-...
193  
-AttributeError: 'ManyRelatedManager' object has no attribute 'remove'
194  
-
195  
-# Here we back up the list of all of Jim's groups.
196  
->>> backup = list(jim.group_set.all())
197  
->>> backup
198  
-[<Group: Rock>, <Group: Roll>]
199  
-
200  
-# The clear function should still work.
201  
->>> jim.group_set.clear()
202  
-
203  
-# Now Jim will be in no groups.
204  
->>> jim.group_set.all()
205  
-[]
206  
-
207  
-# Assignment should not work with models specifying a through model for many of
208  
-# the same reasons as adding.
209  
->>> jim.group_set = backup
210  
-Traceback (most recent call last):
211  
-...
212  
-AttributeError: Cannot set values on a ManyToManyField which specifies an intermediary model.  Use m2m_through.Membership's Manager instead.
213  
-
214  
-# Let's re-save those instances that we've cleared.
215  
->>> m1.save()
216  
->>> m4.save()
217  
-
218  
-# Verifying that those instances were re-saved successfully.
219  
->>> jim.group_set.all()
220  
-[<Group: Rock>, <Group: Roll>]
221  
-
222  
-### Custom Tests ###
223  
-
224  
-# Let's see if we can query through our second relationship.
225  
->>> rock.custom_members.all()
226  
-[]
227  
-
228  
-# We can query in the opposite direction as well.
229  
->>> bob.custom.all()
230  
-[]
231  
-
232  
-# Let's create some membership objects in this custom relationship.
233  
->>> cm1 = CustomMembership.objects.create(person=bob, group=rock)
234  
->>> cm2 = CustomMembership.objects.create(person=jim, group=rock)
235  
-
236  
-# If we get the number of people in Rock, it should be both Bob and Jim.
237  
->>> rock.custom_members.all()
238  
-[<Person: Bob>, <Person: Jim>]
239  
-
240  
-# Bob should only be in one custom group.
241  
->>> bob.custom.all()
242  
-[<Group: Rock>]
243  
-
244  
-# Let's make sure our new descriptors don't conflict with the FK related_name.
245  
->>> bob.custom_person_related_name.all()
246  
-[<CustomMembership: Bob is a member of Rock>]
247  
-
248  
-### SELF-REFERENTIAL TESTS ###
249  
-
250  
-# Let's first create a person who has no friends.
251  
->>> tony = PersonSelfRefM2M.objects.create(name="Tony")
252  
->>> tony.friends.all()
253  
-[]
254  
-
255  
-# Now let's create another person for Tony to be friends with.
256  
->>> chris = PersonSelfRefM2M.objects.create(name="Chris")
257  
->>> f = Friendship.objects.create(first=tony, second=chris, date_friended=datetime.now())
258  
-
259  
-# Tony should now show that Chris is his friend.
260  
->>> tony.friends.all()
261  
-[<PersonSelfRefM2M: Chris>]
262  
-
263  
-# But we haven't established that Chris is Tony's Friend.
264  
->>> chris.friends.all()
265  
-[]
266  
-
267  
-# So let's do that now.
268  
->>> f2 = Friendship.objects.create(first=chris, second=tony, date_friended=datetime.now())
269  
-
270  
-# Having added Chris as a friend, let's make sure that his friend set reflects
271  
-# that addition.
272  
->>> chris.friends.all()
273  
-[<PersonSelfRefM2M: Tony>]
274  
-
275  
-# Chris gets mad and wants to get rid of all of his friends.
276  
->>> chris.friends.clear()
277  
-
278  
-# Now he should not have any more friends.
279  
->>> chris.friends.all()
280  
-[]
281  
-
282  
-# Since this isn't a symmetrical relation, Tony's friend link still exists.
283  
->>> tony.friends.all()
284  
-[<PersonSelfRefM2M: Chris>]
285  
-
286  
-
287  
-
288  
-### QUERY TESTS ###
289  
-
290  
-# We can query for the related model by using its attribute name (members, in
291  
-# this case).
292  
->>> Group.objects.filter(members__name='Bob')
293  
-[<Group: Roll>]
294  
-
295  
-# To query through the intermediary model, we specify its model name.
296  
-# In this case, membership.
297  
->>> Group.objects.filter(membership__invite_reason="She was just awesome.")
298  
-[<Group: Rock>]
299  
-
300  
-# If we want to query in the reverse direction by the related model, use its
301  
-# model name (group, in this case).
302  
->>> Person.objects.filter(group__name="Rock")
303  
-[<Person: Jane>, <Person: Jim>]
304  
-
305  
-# If the m2m field has specified a related_name, using that will work.
306  
->>> Person.objects.filter(custom__name="Rock")
307  
-[<Person: Bob>, <Person: Jim>]
308  
-
309  
-# To query through the intermediary model in the reverse direction, we again
310  
-# specify its model name (membership, in this case).
311  
->>> Person.objects.filter(membership__invite_reason="She was just awesome.")
312  
-[<Person: Jane>]
313  
-
314  
-# Let's see all of the groups that Jane joined after 1 Jan 2005:
315  
->>> Group.objects.filter(membership__date_joined__gt=datetime(2005, 1, 1), membership__person =jane)
316  
-[<Group: Rock>]
317  
-
318  
-# Queries also work in the reverse direction: Now let's see all of the people
319  
-# that have joined Rock since 1 Jan 2005:
320  
->>> Person.objects.filter(membership__date_joined__gt=datetime(2005, 1, 1), membership__group=rock)
321  
-[<Person: Jane>, <Person: Jim>]
322  
-
323  
-# Conceivably, queries through membership could return correct, but non-unique
324  
-# querysets.  To demonstrate this, we query for all people who have joined a
325  
-# group after 2004:
326  
->>> Person.objects.filter(membership__date_joined__gt=datetime(2004, 1, 1))
327  
-[<Person: Jane>, <Person: Jim>, <Person: Jim>]
328  
-
329  
-# Jim showed up twice, because he joined two groups ('Rock', and 'Roll'):
330  
->>> [(m.person.name, m.group.name) for m in
331  
-... Membership.objects.filter(date_joined__gt=datetime(2004, 1, 1))]
332  
-[(u'Jane', u'Rock'), (u'Jim', u'Rock'), (u'Jim', u'Roll')]
333  
-
334  
-# QuerySet's distinct() method can correct this problem.
335  
->>> Person.objects.filter(membership__date_joined__gt=datetime(2004, 1, 1)).distinct()
336  
-[<Person: Jane>, <Person: Jim>]
337  
-"""}
343  tests/modeltests/m2m_through/tests.py
... ...
@@ -0,0 +1,343 @@
  1
+from datetime import datetime
  2
+from operator import attrgetter
  3
+
  4
+from django.test import TestCase
  5
+
  6
+from models import Person, Group, Membership, CustomMembership, \
  7
+    TestNoDefaultsOrNulls, PersonSelfRefM2M, Friendship
  8
+
  9
+
  10
+class M2mThroughTests(TestCase):
  11
+    def setUp(self):
  12
+        self.bob = Person.objects.create(name='Bob')
  13
+        self.jim = Person.objects.create(name='Jim')
  14
+        self.jane = Person.objects.create(name='Jane')
  15
+        self.rock = Group.objects.create(name='Rock')
  16
+        self.roll = Group.objects.create(name='Roll')
  17
+
  18
+    def test_m2m_through(self):
  19
+        # We start out by making sure that the Group 'rock' has no members.
  20
+        self.assertQuerysetEqual(
  21
+            self.rock.members.all(),
  22
+            []
  23
+        )
  24
+        # To make Jim a member of Group Rock, simply create a Membership object.
  25
+        m1 = Membership.objects.create(person=self.jim, group=self.rock)
  26
+        # We can do the same for Jane and Rock.
  27
+        m2 = Membership.objects.create(person=self.jane, group=self.rock)
  28
+        # Let's check to make sure that it worked.  Jane and Jim should be members of Rock.
  29
+        self.assertQuerysetEqual(
  30
+            self.rock.members.all(), [
  31
+                'Jane',
  32
+                'Jim'
  33
+            ],
  34
+            attrgetter("name")
  35
+        )
  36
+        # Now we can add a bunch more Membership objects to test with.
  37
+        m3 = Membership.objects.create(person=self.bob, group=self.roll)
  38
+        m4 = Membership.objects.create(person=self.jim, group=self.roll)
  39
+        m5 = Membership.objects.create(person=self.jane, group=self.roll)
  40
+        # We can get Jim's Group membership as with any ForeignKey.
  41
+        self.assertQuerysetEqual(
  42
+            self.jim.group_set.all(), [
  43
+                'Rock',
  44
+                'Roll'
  45
+            ],
  46
+            attrgetter("name")
  47
+        )
  48
+        # Querying the intermediary model works like normal.
  49
+        self.assertEqual(
  50
+            repr(Membership.objects.get(person=self.jane, group=self.rock)),
  51
+            '<Membership: Jane is a member of Rock>'
  52
+        )
  53
+        # It's not only get that works. Filter works like normal as well.
  54
+        self.assertQuerysetEqual(
  55
+            Membership.objects.filter(person=self.jim), [
  56
+                '<Membership: Jim is a member of Rock>',
  57
+                '<Membership: Jim is a member of Roll>'
  58
+            ]
  59
+        )
  60
+        self.rock.members.clear()
  61
+        # Now there will be no members of Rock.
  62
+        self.assertQuerysetEqual(
  63
+            self.rock.members.all(),
  64
+            []
  65
+        )
  66
+
  67
+
  68
+
  69
+    def test_forward_descriptors(self):
  70
+        # Due to complications with adding via an intermediary model,
  71
+        # the add method is not provided.
  72
+        self.assertRaises(AttributeError, lambda: self.rock.members.add(self.bob))
  73
+        # Create is also disabled as it suffers from the same problems as add.
  74
+        self.assertRaises(AttributeError, lambda: self.rock.members.create(name='Anne'))
  75
+        # Remove has similar complications, and is not provided either.
  76
+        self.assertRaises(AttributeError, lambda: self.rock.members.remove(self.jim))
  77
+
  78
+        m1 = Membership.objects.create(person=self.jim, group=self.rock)
  79
+        m2 = Membership.objects.create(person=self.jane, group=self.rock)
  80
+
  81
+        # Here we back up the list of all members of Rock.
  82
+        backup = list(self.rock.members.all())
  83
+        # ...and we verify that it has worked.
  84
+        self.assertEqual(
  85
+            [p.name for p in backup],
  86
+            ['Jane', 'Jim']
  87
+        )
  88
+        # The clear function should still work.
  89
+        self.rock.members.clear()
  90
+        # Now there will be no members of Rock.
  91
+        self.assertQuerysetEqual(
  92
+            self.rock.members.all(),
  93
+            []
  94
+        )
  95
+
  96
+        # Assignment should not work with models specifying a through model for many of
  97
+        # the same reasons as adding.
  98
+        self.assertRaises(AttributeError, setattr, self.rock, "members", backup)
  99
+        # Let's re-save those instances that we've cleared.
  100
+        m1.save()
  101
+        m2.save()
  102
+        # Verifying that those instances were re-saved successfully.
  103
+        self.assertQuerysetEqual(
  104
+            self.rock.members.all(),[
  105
+                'Jane',
  106
+                'Jim'
  107
+            ],
  108
+            attrgetter("name")
  109
+        )
  110
+
  111
+    def test_reverse_descriptors(self):
  112
+        # Due to complications with adding via an intermediary model,
  113
+        # the add method is not provided.
  114
+        self.assertRaises(AttributeError, lambda: self.bob.group_set.add(self.rock))
  115
+        # Create is also disabled as it suffers from the same problems as add.
  116
+        self.assertRaises(AttributeError, lambda: self.bob.group_set.create(name="funk"))
  117
+        # Remove has similar complications, and is not provided either.
  118
+        self.assertRaises(AttributeError, lambda: self.jim.group_set.remove(self.rock))
  119
+
  120
+        m1 = Membership.objects.create(person=self.jim, group=self.rock)
  121
+        m2 = Membership.objects.create(person=self.jim, group=self.roll)
  122
+
  123
+        # Here we back up the list of all of Jim's groups.
  124
+        backup = list(self.jim.group_set.all())
  125
+        self.assertEqual(
  126
+            [g.name for g in backup],
  127
+            ['Rock', 'Roll']
  128
+        )
  129
+        # The clear function should still work.
  130
+        self.jim.group_set.clear()
  131
+        # Now Jim will be in no groups.
  132
+        self.assertQuerysetEqual(
  133
+            self.jim.group_set.all(),
  134
+            []
  135
+        )
  136
+        # Assignment should not work with models specifying a through model for many of
  137
+        # the same reasons as adding.
  138
+        self.assertRaises(AttributeError, setattr, self.jim, "group_set", backup)
  139
+        # Let's re-save those instances that we've cleared.
  140
+
  141
+        m1.save()
  142
+        m2.save()
  143
+        # Verifying that those instances were re-saved successfully.
  144
+        self.assertQuerysetEqual(
  145
+            self.jim.group_set.all(),[
  146
+                'Rock',
  147
+                'Roll'
  148
+            ],
  149
+            attrgetter("name")
  150
+        )
  151
+
  152
+    def test_custom_tests(self):
  153
+        # Let's see if we can query through our second relationship.
  154
+        self.assertQuerysetEqual(
  155
+            self.rock.custom_members.all(),
  156
+            []
  157
+        )
  158
+        # We can query in the opposite direction as well.
  159
+        self.assertQuerysetEqual(
  160
+            self.bob.custom.all(),
  161
+            []
  162
+        )
  163
+
  164
+        cm1 = CustomMembership.objects.create(person=self.bob, group=self.rock)
  165
+        cm2 = CustomMembership.objects.create(person=self.jim, group=self.rock)
  166
+
  167
+        # If we get the number of people in Rock, it should be both Bob and Jim.
  168
+        self.assertQuerysetEqual(
  169
+            self.rock.custom_members.all(),[
  170
+                'Bob',
  171
+                'Jim'
  172
+            ],
  173
+            attrgetter("name")
  174
+        )
  175
+        # Bob should only be in one custom group.
  176
+        self.assertQuerysetEqual(
  177
+            self.bob.custom.all(),[
  178
+                'Rock'
  179
+            ],
  180
+            attrgetter("name")
  181
+        )
  182
+        # Let's make sure our new descriptors don't conflict with the FK related_name.
  183
+        self.assertQuerysetEqual(
  184
+            self.bob.custom_person_related_name.all(),[
  185
+                '<CustomMembership: Bob is a member of Rock>'
  186
+            ]
  187
+        )
  188
+
  189
+    def test_self_referential_tests(self):
  190
+        # Let's first create a person who has no friends.
  191
+        tony = PersonSelfRefM2M.objects.create(name="Tony")
  192
+        self.assertQuerysetEqual(
  193
+            tony.friends.all(),
  194
+            []
  195
+        )
  196
+
  197
+        chris = PersonSelfRefM2M.objects.create(name="Chris")
  198
+        f = Friendship.objects.create(first=tony, second=chris, date_friended=datetime.now())
  199
+
  200
+        # Tony should now show that Chris is his friend.
  201
+        self.assertQuerysetEqual(
  202
+            tony.friends.all(),[
  203
+                'Chris'
  204
+            ],
  205
+            attrgetter("name")
  206
+        )
  207
+        # But we haven't established that Chris is Tony's Friend.
  208
+        self.assertQuerysetEqual(
  209
+            chris.friends.all(),
  210
+            []
  211
+        )
  212
+        f2 = Friendship.objects.create(first=chris, second=tony, date_friended=datetime.now())
  213
+
  214
+        # Having added Chris as a friend, let's make sure that his friend set reflects
  215
+        # that addition.
  216
+        self.assertQuerysetEqual(
  217
+            chris.friends.all(),[
  218
+                'Tony'
  219
+            ],
  220
+            attrgetter("name")
  221
+        )
  222
+
  223
+        # Chris gets mad and wants to get rid of all of his friends.
  224
+        chris.friends.clear()
  225
+        # Now he should not have any more friends.
  226
+        self.assertQuerysetEqual(
  227
+            chris.friends.all(),
  228
+            []
  229
+        )
  230
+        # Since this isn't a symmetrical relation, Tony's friend link still exists.
  231
+        self.assertQuerysetEqual(
  232
+            tony.friends.all(),[
  233
+                'Chris'
  234
+            ],
  235
+            attrgetter("name")
  236
+        )
  237
+
  238
+    def test_query_tests(self):
  239
+        m1 = Membership.objects.create(person=self.jim, group=self.rock)
  240
+        m2 = Membership.objects.create(person=self.jane, group=self.rock)
  241
+        m3 = Membership.objects.create(person=self.bob, group=self.roll)
  242
+        m4 = Membership.objects.create(person=self.jim, group=self.roll)
  243
+        m5 = Membership.objects.create(person=self.jane, group=self.roll)
  244
+
  245
+        m2.invite_reason = "She was just awesome."
  246
+        m2.date_joined = datetime(2006, 1, 1)
  247
+        m2.save()
  248
+        m3.date_joined = datetime(2004, 1, 1)
  249
+        m3.save()
  250
+        m5.date_joined = datetime(2004, 1, 1)
  251
+        m5.save()
  252
+
  253
+        # We can query for the related model by using its attribute name (members, in
  254
+        # this case).
  255
+        self.assertQuerysetEqual(
  256
+            Group.objects.filter(members__name='Bob'),[
  257
+                'Roll'
  258
+            ],
  259
+            attrgetter("name")
  260
+        )
  261
+
  262
+        # To query through the intermediary model, we specify its model name.
  263
+        # In this case, membership.
  264
+        self.assertQuerysetEqual(
  265
+            Group.objects.filter(membership__invite_reason="She was just awesome."),[
  266
+                'Rock'
  267
+            ],
  268
+            attrgetter("name")
  269
+        )
  270
+
  271
+        # If we want to query in the reverse direction by the related model, use its
  272
+        # model name (group, in this case).
  273
+        self.assertQuerysetEqual(
  274
+            Person.objects.filter(group__name="Rock"),[
  275
+                'Jane',
  276
+                'Jim'
  277
+            ],
  278
+            attrgetter("name")
  279
+        )
  280
+
  281
+        cm1 = CustomMembership.objects.create(person=self.bob, group=self.rock)
  282
+        cm2 = CustomMembership.objects.create(person=self.jim, group=self.rock)
  283
+        # If the m2m field has specified a related_name, using that will work.
  284
+        self.assertQuerysetEqual(
  285
+            Person.objects.filter(custom__name="Rock"),[
  286
+                'Bob',
  287
+                'Jim'
  288
+            ],
  289
+            attrgetter("name")
  290
+        )
  291
+
  292
+        # To query through the intermediary model in the reverse direction, we again
  293
+        # specify its model name (membership, in this case).
  294
+        self.assertQuerysetEqual(
  295
+            Person.objects.filter(membership__invite_reason="She was just awesome."),[
  296
+                'Jane'
  297
+            ],
  298
+            attrgetter("name")
  299
+        )
  300
+
  301
+        # Let's see all of the groups that Jane joined after 1 Jan 2005:
  302
+        self.assertQuerysetEqual(
  303
+            Group.objects.filter(membership__date_joined__gt=datetime(2005, 1, 1), membership__person=self.jane),[
  304
+                'Rock'
  305
+            ],
  306
+            attrgetter("name")
  307
+        )
  308
+
  309
+        # Queries also work in the reverse direction: Now let's see all of the people
  310
+        # that have joined Rock since 1 Jan 2005:
  311
+        self.assertQuerysetEqual(
  312
+            Person.objects.filter(membership__date_joined__gt=datetime(2005, 1, 1), membership__group=self.rock),[
  313
+                'Jane',
  314
+                'Jim'
  315
+            ],
  316
+            attrgetter("name")
  317
+        )
  318
+
  319
+        # Conceivably, queries through membership could return correct, but non-unique
  320
+        # querysets.  To demonstrate this, we query for all people who have joined a
  321
+        # group after 2004:
  322
+        self.assertQuerysetEqual(
  323
+            Person.objects.filter(membership__date_joined__gt=datetime(2004, 1, 1)),[
  324
+                'Jane',
  325
+                'Jim',
  326
+                'Jim'
  327
+            ],
  328
+            attrgetter("name")
  329
+        )
  330
+
  331
+        # Jim showed up twice, because he joined two groups ('Rock', and 'Roll'):
  332
+        self.assertEqual(
  333
+            [(m.person.name, m.group.name) for m in Membership.objects.filter(date_joined__gt=datetime(2004, 1, 1))],
  334
+            [(u'Jane', u'Rock'), (u'Jim', u'Rock'), (u'Jim', u'Roll')]
  335
+        )
  336
+        # QuerySet's distinct() method can correct this problem.
  337
+        self.assertQuerysetEqual(
  338
+            Person.objects.filter(membership__date_joined__gt=datetime(2004, 1, 1)).distinct(),[
  339
+                'Jane',
  340
+                'Jim'
  341
+            ],
  342
+            attrgetter("name")
  343
+        )

0 notes on commit e0a1e47

Please sign in to comment.
Something went wrong with that request. Please try again.