~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to tests/foreign_object/tests.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import datetime
 
2
from operator import attrgetter
 
3
 
 
4
from .models import (
 
5
    Country, Person, Group, Membership, Friendship, Article,
 
6
    ArticleTranslation, ArticleTag, ArticleIdea, NewsArticle)
 
7
from django.test import TestCase
 
8
from django.utils.translation import activate
 
9
from django.core.exceptions import FieldError
 
10
from django import forms
 
11
 
 
12
# Note that these tests are testing internal implementation details.
 
13
# ForeignObject is not part of public API.
 
14
 
 
15
class MultiColumnFKTests(TestCase):
 
16
    def setUp(self):
 
17
        # Creating countries
 
18
        self.usa = Country.objects.create(name="United States of America")
 
19
        self.soviet_union = Country.objects.create(name="Soviet Union")
 
20
        Person()
 
21
        # Creating People
 
22
        self.bob = Person()
 
23
        self.bob.name = 'Bob'
 
24
        self.bob.person_country = self.usa
 
25
        self.bob.save()
 
26
        self.jim = Person.objects.create(name='Jim', person_country=self.usa)
 
27
        self.george = Person.objects.create(name='George', person_country=self.usa)
 
28
 
 
29
        self.jane = Person.objects.create(name='Jane', person_country=self.soviet_union)
 
30
        self.mark = Person.objects.create(name='Mark', person_country=self.soviet_union)
 
31
        self.sam = Person.objects.create(name='Sam', person_country=self.soviet_union)
 
32
 
 
33
        # Creating Groups
 
34
        self.kgb = Group.objects.create(name='KGB', group_country=self.soviet_union)
 
35
        self.cia = Group.objects.create(name='CIA', group_country=self.usa)
 
36
        self.republican = Group.objects.create(name='Republican', group_country=self.usa)
 
37
        self.democrat = Group.objects.create(name='Democrat', group_country=self.usa)
 
38
 
 
39
    def test_get_succeeds_on_multicolumn_match(self):
 
40
        # Membership objects have access to their related Person if both
 
41
        # country_ids match between them
 
42
        membership = Membership.objects.create(
 
43
            membership_country_id=self.usa.id, person_id=self.bob.id, group_id=self.cia.id)
 
44
 
 
45
        person = membership.person
 
46
        self.assertEqual((person.id, person.name), (self.bob.id, "Bob"))
 
47
 
 
48
    def test_get_fails_on_multicolumn_mismatch(self):
 
49
        # Membership objects returns DoesNotExist error when the there is no
 
50
        # Person with the same id and country_id
 
51
        membership = Membership.objects.create(
 
52
            membership_country_id=self.usa.id, person_id=self.jane.id, group_id=self.cia.id)
 
53
 
 
54
        self.assertRaises(Person.DoesNotExist, getattr, membership, 'person')
 
55
 
 
56
    def test_reverse_query_returns_correct_result(self):
 
57
        # Creating a valid membership because it has the same country has the person
 
58
        Membership.objects.create(
 
59
            membership_country_id=self.usa.id, person_id=self.bob.id, group_id=self.cia.id)
 
60
 
 
61
        # Creating an invalid membership because it has a different country has the person
 
62
        Membership.objects.create(
 
63
            membership_country_id=self.soviet_union.id, person_id=self.bob.id,
 
64
            group_id=self.republican.id)
 
65
 
 
66
        self.assertQuerysetEqual(
 
67
            self.bob.membership_set.all(), [
 
68
                self.cia.id
 
69
            ],
 
70
            attrgetter("group_id")
 
71
        )
 
72
 
 
73
    def test_query_filters_correctly(self):
 
74
 
 
75
        # Creating a to valid memberships
 
76
        Membership.objects.create(
 
77
            membership_country_id=self.usa.id, person_id=self.bob.id, group_id=self.cia.id)
 
78
        Membership.objects.create(
 
79
            membership_country_id=self.usa.id, person_id=self.jim.id,
 
80
            group_id=self.cia.id)
 
81
 
 
82
        # Creating an invalid membership
 
83
        Membership.objects.create(membership_country_id=self.soviet_union.id,
 
84
                                  person_id=self.george.id, group_id=self.cia.id)
 
85
 
 
86
        self.assertQuerysetEqual(
 
87
            Membership.objects.filter(person__name__contains='o'), [
 
88
                self.bob.id
 
89
            ],
 
90
            attrgetter("person_id")
 
91
        )
 
92
 
 
93
    def test_reverse_query_filters_correctly(self):
 
94
 
 
95
        timemark = datetime.datetime.utcnow()
 
96
        timedelta = datetime.timedelta(days=1)
 
97
 
 
98
        # Creating a to valid memberships
 
99
        Membership.objects.create(
 
100
            membership_country_id=self.usa.id, person_id=self.bob.id,
 
101
            group_id=self.cia.id, date_joined=timemark - timedelta)
 
102
        Membership.objects.create(
 
103
            membership_country_id=self.usa.id, person_id=self.jim.id,
 
104
            group_id=self.cia.id, date_joined=timemark + timedelta)
 
105
 
 
106
        # Creating an invalid membership
 
107
        Membership.objects.create(
 
108
            membership_country_id=self.soviet_union.id, person_id=self.george.id,
 
109
            group_id=self.cia.id, date_joined=timemark + timedelta)
 
110
 
 
111
        self.assertQuerysetEqual(
 
112
            Person.objects.filter(membership__date_joined__gte=timemark), [
 
113
                'Jim'
 
114
            ],
 
115
            attrgetter('name')
 
116
        )
 
117
 
 
118
    def test_forward_in_lookup_filters_correctly(self):
 
119
        Membership.objects.create(membership_country_id=self.usa.id, person_id=self.bob.id,
 
120
                                  group_id=self.cia.id)
 
121
        Membership.objects.create(membership_country_id=self.usa.id, person_id=self.jim.id,
 
122
                                  group_id=self.cia.id)
 
123
 
 
124
        # Creating an invalid membership
 
125
        Membership.objects.create(
 
126
            membership_country_id=self.soviet_union.id, person_id=self.george.id,
 
127
            group_id=self.cia.id)
 
128
 
 
129
        self.assertQuerysetEqual(
 
130
            Membership.objects.filter(person__in=[self.george, self.jim]), [
 
131
                self.jim.id,
 
132
            ],
 
133
            attrgetter('person_id')
 
134
        )
 
135
 
 
136
        self.assertQuerysetEqual(
 
137
            Membership.objects.filter(person__in=Person.objects.filter(name='Jim')), [
 
138
                self.jim.id,
 
139
            ],
 
140
            attrgetter('person_id')
 
141
        )
 
142
 
 
143
    def test_select_related_foreignkey_forward_works(self):
 
144
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
145
        Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
 
146
 
 
147
        with self.assertNumQueries(1):
 
148
            people = [m.person for m in Membership.objects.select_related('person').order_by('pk')]
 
149
 
 
150
        normal_people = [m.person for m in Membership.objects.all().order_by('pk')]
 
151
        self.assertEqual(people, normal_people)
 
152
 
 
153
    def test_prefetch_foreignkey_forward_works(self):
 
154
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
155
        Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
 
156
 
 
157
        with self.assertNumQueries(2):
 
158
            people = [
 
159
                m.person for m in Membership.objects.prefetch_related('person').order_by('pk')]
 
160
 
 
161
        normal_people = [m.person for m in Membership.objects.order_by('pk')]
 
162
        self.assertEqual(people, normal_people)
 
163
 
 
164
    def test_prefetch_foreignkey_reverse_works(self):
 
165
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
166
        Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
 
167
        with self.assertNumQueries(2):
 
168
            membership_sets = [
 
169
                list(p.membership_set.all())
 
170
                for p in Person.objects.prefetch_related('membership_set').order_by('pk')]
 
171
 
 
172
        normal_membership_sets = [list(p.membership_set.all())
 
173
                                  for p in Person.objects.order_by('pk')]
 
174
        self.assertEqual(membership_sets, normal_membership_sets)
 
175
 
 
176
    def test_m2m_through_forward_returns_valid_members(self):
 
177
        # We start out by making sure that the Group 'CIA' has no members.
 
178
        self.assertQuerysetEqual(
 
179
            self.cia.members.all(),
 
180
            []
 
181
        )
 
182
 
 
183
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
184
        Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.cia)
 
185
 
 
186
        # Let's check to make sure that it worked.  Bob and Jim should be members of the CIA.
 
187
 
 
188
        self.assertQuerysetEqual(
 
189
            self.cia.members.all(), [
 
190
                'Bob',
 
191
                'Jim'
 
192
            ], attrgetter("name")
 
193
        )
 
194
 
 
195
    def test_m2m_through_reverse_returns_valid_members(self):
 
196
        # We start out by making sure that Bob is in no groups.
 
197
        self.assertQuerysetEqual(
 
198
            self.bob.groups.all(),
 
199
            []
 
200
        )
 
201
 
 
202
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
203
        Membership.objects.create(membership_country=self.usa, person=self.bob,
 
204
                                  group=self.republican)
 
205
 
 
206
        # Bob should be in the CIA and a Republican
 
207
        self.assertQuerysetEqual(
 
208
            self.bob.groups.all(), [
 
209
                'CIA',
 
210
                'Republican'
 
211
            ], attrgetter("name")
 
212
        )
 
213
 
 
214
    def test_m2m_through_forward_ignores_invalid_members(self):
 
215
        # We start out by making sure that the Group 'CIA' has no members.
 
216
        self.assertQuerysetEqual(
 
217
            self.cia.members.all(),
 
218
            []
 
219
        )
 
220
 
 
221
        # Something adds jane to group CIA but Jane is in Soviet Union which isn't CIA's country
 
222
        Membership.objects.create(membership_country=self.usa, person=self.jane, group=self.cia)
 
223
 
 
224
        # There should still be no members in CIA
 
225
        self.assertQuerysetEqual(
 
226
            self.cia.members.all(),
 
227
            []
 
228
        )
 
229
 
 
230
    def test_m2m_through_reverse_ignores_invalid_members(self):
 
231
        # We start out by making sure that Jane has no groups.
 
232
        self.assertQuerysetEqual(
 
233
            self.jane.groups.all(),
 
234
            []
 
235
        )
 
236
 
 
237
        # Something adds jane to group CIA but Jane is in Soviet Union which isn't CIA's country
 
238
        Membership.objects.create(membership_country=self.usa, person=self.jane, group=self.cia)
 
239
 
 
240
        # Jane should still not be in any groups
 
241
        self.assertQuerysetEqual(
 
242
            self.jane.groups.all(),
 
243
            []
 
244
        )
 
245
 
 
246
    def test_m2m_through_on_self_works(self):
 
247
        self.assertQuerysetEqual(
 
248
            self.jane.friends.all(),
 
249
            []
 
250
        )
 
251
 
 
252
        Friendship.objects.create(
 
253
            from_friend_country=self.jane.person_country, from_friend=self.jane,
 
254
            to_friend_country=self.george.person_country, to_friend=self.george)
 
255
 
 
256
        self.assertQuerysetEqual(
 
257
            self.jane.friends.all(),
 
258
            ['George'], attrgetter("name")
 
259
        )
 
260
 
 
261
    def test_m2m_through_on_self_ignores_mismatch_columns(self):
 
262
        self.assertQuerysetEqual(self.jane.friends.all(), [])
 
263
 
 
264
        # Note that we use ids instead of instances. This is because instances on ForeignObject
 
265
        # properties will set all related field off of the given instance
 
266
        Friendship.objects.create(
 
267
            from_friend_id=self.jane.id, to_friend_id=self.george.id,
 
268
            to_friend_country_id=self.jane.person_country_id,
 
269
            from_friend_country_id=self.george.person_country_id)
 
270
 
 
271
        self.assertQuerysetEqual(self.jane.friends.all(), [])
 
272
 
 
273
    def test_prefetch_related_m2m_foward_works(self):
 
274
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
275
        Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
 
276
 
 
277
        with self.assertNumQueries(2):
 
278
            members_lists = [list(g.members.all())
 
279
                             for g in Group.objects.prefetch_related('members')]
 
280
 
 
281
        normal_members_lists = [list(g.members.all()) for g in Group.objects.all()]
 
282
        self.assertEqual(members_lists, normal_members_lists)
 
283
 
 
284
    def test_prefetch_related_m2m_reverse_works(self):
 
285
        Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
 
286
        Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
 
287
 
 
288
        with self.assertNumQueries(2):
 
289
            groups_lists = [list(p.groups.all()) for p in Person.objects.prefetch_related('groups')]
 
290
 
 
291
        normal_groups_lists = [list(p.groups.all()) for p in Person.objects.all()]
 
292
        self.assertEqual(groups_lists, normal_groups_lists)
 
293
 
 
294
    def test_translations(self):
 
295
        activate('fi')
 
296
        a1 = Article.objects.create(pub_date=datetime.date.today())
 
297
        at1_fi = ArticleTranslation(article=a1, lang='fi', title='Otsikko', body='Diipadaapa')
 
298
        at1_fi.save()
 
299
        at2_en = ArticleTranslation(article=a1, lang='en', title='Title', body='Lalalalala')
 
300
        at2_en.save()
 
301
        with self.assertNumQueries(1):
 
302
            fetched = Article.objects.select_related('active_translation').get(
 
303
                active_translation__title='Otsikko')
 
304
            self.assertTrue(fetched.active_translation.title == 'Otsikko')
 
305
        a2 = Article.objects.create(pub_date=datetime.date.today())
 
306
        at2_fi = ArticleTranslation(article=a2, lang='fi', title='Atsikko', body='Diipadaapa',
 
307
                                    abstract='dipad')
 
308
        at2_fi.save()
 
309
        a3 = Article.objects.create(pub_date=datetime.date.today())
 
310
        at3_en = ArticleTranslation(article=a3, lang='en', title='A title', body='lalalalala',
 
311
                                    abstract='lala')
 
312
        at3_en.save()
 
313
        # Test model initialization with active_translation field.
 
314
        a3 = Article(id=a3.id, pub_date=a3.pub_date, active_translation=at3_en)
 
315
        a3.save()
 
316
        self.assertEqual(
 
317
            list(Article.objects.filter(active_translation__abstract=None)),
 
318
            [a1, a3])
 
319
        self.assertEqual(
 
320
            list(Article.objects.filter(active_translation__abstract=None,
 
321
                                        active_translation__pk__isnull=False)),
 
322
            [a1])
 
323
        activate('en')
 
324
        self.assertEqual(
 
325
            list(Article.objects.filter(active_translation__abstract=None)),
 
326
            [a1, a2])
 
327
 
 
328
    def test_foreign_key_raises_informative_does_not_exist(self):
 
329
        referrer = ArticleTranslation()
 
330
        with self.assertRaisesMessage(Article.DoesNotExist, 'ArticleTranslation has no article'):
 
331
            referrer.article
 
332
 
 
333
    def test_foreign_key_related_query_name(self):
 
334
        a1 = Article.objects.create(pub_date=datetime.date.today())
 
335
        ArticleTag.objects.create(article=a1, name="foo")
 
336
        self.assertEqual(Article.objects.filter(tag__name="foo").count(), 1)
 
337
        self.assertEqual(Article.objects.filter(tag__name="bar").count(), 0)
 
338
        with self.assertRaises(FieldError):
 
339
            Article.objects.filter(tags__name="foo")
 
340
 
 
341
    def test_many_to_many_related_query_name(self):
 
342
        a1 = Article.objects.create(pub_date=datetime.date.today())
 
343
        i1 = ArticleIdea.objects.create(name="idea1")
 
344
        a1.ideas.add(i1)
 
345
        self.assertEqual(Article.objects.filter(idea_things__name="idea1").count(), 1)
 
346
        self.assertEqual(Article.objects.filter(idea_things__name="idea2").count(), 0)
 
347
        with self.assertRaises(FieldError):
 
348
            Article.objects.filter(ideas__name="idea1")
 
349
 
 
350
    def test_inheritance(self):
 
351
        activate("fi")
 
352
        na = NewsArticle.objects.create(pub_date=datetime.date.today())
 
353
        ArticleTranslation.objects.create(
 
354
            article=na, lang="fi", title="foo", body="bar")
 
355
        self.assertQuerysetEqual(
 
356
            NewsArticle.objects.select_related('active_translation'),
 
357
            [na], lambda x: x
 
358
        )
 
359
        with self.assertNumQueries(1):
 
360
            self.assertEqual(
 
361
                NewsArticle.objects.select_related(
 
362
                    'active_translation')[0].active_translation.title,
 
363
                "foo")
 
364
 
 
365
class FormsTests(TestCase):
 
366
    # ForeignObjects should not have any form fields, currently the user needs
 
367
    # to manually deal with the foreignobject relation.
 
368
    class ArticleForm(forms.ModelForm):
 
369
        class Meta:
 
370
            model = Article
 
371
            fields = '__all__'
 
372
 
 
373
    def test_foreign_object_form(self):
 
374
        # A very crude test checking that the non-concrete fields do not get form fields.
 
375
        form = FormsTests.ArticleForm()
 
376
        self.assertIn('id_pub_date', form.as_table())
 
377
        self.assertNotIn('active_translation', form.as_table())
 
378
        form = FormsTests.ArticleForm(data={'pub_date': str(datetime.date.today())})
 
379
        self.assertTrue(form.is_valid())
 
380
        a = form.save()
 
381
        self.assertEqual(a.pub_date, datetime.date.today())
 
382
        form = FormsTests.ArticleForm(instance=a, data={'pub_date': '2013-01-01'})
 
383
        a2 = form.save()
 
384
        self.assertEqual(a.pk, a2.pk)
 
385
        self.assertEqual(a2.pub_date, datetime.date(2013, 1, 1))