PageRenderTime 199ms CodeModel.GetById 168ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/modeltests/basic/tests.py

https://code.google.com/p/mango-py/
Python | 554 lines | 407 code | 74 blank | 73 comment | 6 complexity | ab9b8e9cf6d858c58028501b1f8bab6d MD5 | raw file
  1from datetime import datetime
  2
  3from django.core.exceptions import ObjectDoesNotExist
  4from django.db import models, DEFAULT_DB_ALIAS, connection
  5from django.db.models.fields import FieldDoesNotExist
  6from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
  7
  8from models import Article
  9
 10
 11class ModelTest(TestCase):
 12
 13    def test_lookup(self):
 14        # No articles are in the system yet.
 15        self.assertQuerysetEqual(Article.objects.all(), [])
 16
 17        # Create an Article.
 18        a = Article(
 19            id=None,
 20            headline='Area man programs in Python',
 21            pub_date=datetime(2005, 7, 28),
 22        )
 23
 24        # Save it into the database. You have to call save() explicitly.
 25        a.save()
 26
 27        # Now it has an ID.
 28        self.assertTrue(a.id != None)
 29
 30        # Models have a pk property that is an alias for the primary key
 31        # attribute (by default, the 'id' attribute).
 32        self.assertEqual(a.pk, a.id)
 33
 34        # Access database columns via Python attributes.
 35        self.assertEqual(a.headline, 'Area man programs in Python')
 36        self.assertEqual(a.pub_date, datetime(2005, 7, 28, 0, 0))
 37
 38        # Change values by changing the attributes, then calling save().
 39        a.headline = 'Area woman programs in Python'
 40        a.save()
 41
 42        # Article.objects.all() returns all the articles in the database.
 43        self.assertQuerysetEqual(Article.objects.all(),
 44            ['<Article: Area woman programs in Python>'])
 45
 46        # Django provides a rich database lookup API.
 47        self.assertEqual(Article.objects.get(id__exact=a.id), a)
 48        self.assertEqual(Article.objects.get(headline__startswith='Area woman'), a)
 49        self.assertEqual(Article.objects.get(pub_date__year=2005), a)
 50        self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7), a)
 51        self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28), a)
 52        self.assertEqual(Article.objects.get(pub_date__week_day=5), a)
 53
 54        # The "__exact" lookup type can be omitted, as a shortcut.
 55        self.assertEqual(Article.objects.get(id=a.id), a)
 56        self.assertEqual(Article.objects.get(headline='Area woman programs in Python'), a)
 57
 58        self.assertQuerysetEqual(
 59            Article.objects.filter(pub_date__year=2005),
 60            ['<Article: Area woman programs in Python>'],
 61        )
 62        self.assertQuerysetEqual(
 63            Article.objects.filter(pub_date__year=2004),
 64            [],
 65        )
 66        self.assertQuerysetEqual(
 67            Article.objects.filter(pub_date__year=2005, pub_date__month=7),
 68            ['<Article: Area woman programs in Python>'],
 69        )
 70
 71        self.assertQuerysetEqual(
 72            Article.objects.filter(pub_date__week_day=5),
 73            ['<Article: Area woman programs in Python>'],
 74        )
 75        self.assertQuerysetEqual(
 76            Article.objects.filter(pub_date__week_day=6),
 77            [],
 78        )
 79
 80        # Django raises an Article.DoesNotExist exception for get() if the
 81        # parameters don't match any object.
 82        self.assertRaisesRegexp(
 83            ObjectDoesNotExist,
 84            "Article matching query does not exist.",
 85            Article.objects.get,
 86            id__exact=2000,
 87        )
 88
 89        self.assertRaisesRegexp(
 90            ObjectDoesNotExist,
 91            "Article matching query does not exist.",
 92            Article.objects.get,
 93            pub_date__year=2005,
 94            pub_date__month=8,
 95        )
 96
 97        self.assertRaisesRegexp(
 98            ObjectDoesNotExist,
 99            "Article matching query does not exist.",
100            Article.objects.get,
101            pub_date__week_day=6,
102        )
103
104        # Lookup by a primary key is the most common case, so Django
105        # provides a shortcut for primary-key exact lookups.
106        # The following is identical to articles.get(id=a.id).
107        self.assertEqual(Article.objects.get(pk=a.id), a)
108
109        # pk can be used as a shortcut for the primary key name in any query.
110        self.assertQuerysetEqual(Article.objects.filter(pk__in=[a.id]),
111            ["<Article: Area woman programs in Python>"])
112
113        # Model instances of the same type and same ID are considered equal.
114        a = Article.objects.get(pk=a.id)
115        b = Article.objects.get(pk=a.id)
116        self.assertEqual(a, b)
117
118    def test_object_creation(self):
119        # Create an Article.
120        a = Article(
121            id=None,
122            headline='Area man programs in Python',
123            pub_date=datetime(2005, 7, 28),
124        )
125
126        # Save it into the database. You have to call save() explicitly.
127        a.save()
128
129        # You can initialize a model instance using positional arguments,
130        # which should match the field order as defined in the model.
131        a2 = Article(None, 'Second article', datetime(2005, 7, 29))
132        a2.save()
133
134        self.assertNotEqual(a2.id, a.id)
135        self.assertEqual(a2.headline, 'Second article')
136        self.assertEqual(a2.pub_date, datetime(2005, 7, 29, 0, 0))
137
138        # ...or, you can use keyword arguments.
139        a3 = Article(
140            id=None,
141            headline='Third article',
142            pub_date=datetime(2005, 7, 30),
143        )
144        a3.save()
145
146        self.assertNotEqual(a3.id, a.id)
147        self.assertNotEqual(a3.id, a2.id)
148        self.assertEqual(a3.headline, 'Third article')
149        self.assertEqual(a3.pub_date, datetime(2005, 7, 30, 0, 0))
150
151        # You can also mix and match position and keyword arguments, but
152        # be sure not to duplicate field information.
153        a4 = Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
154        a4.save()
155        self.assertEqual(a4.headline, 'Fourth article')
156
157        # Don't use invalid keyword arguments.
158        self.assertRaisesRegexp(
159            TypeError,
160            "'foo' is an invalid keyword argument for this function",
161            Article,
162            id=None,
163            headline='Invalid',
164            pub_date=datetime(2005, 7, 31),
165            foo='bar',
166        )
167
168        # You can leave off the value for an AutoField when creating an
169        # object, because it'll get filled in automatically when you save().
170        a5 = Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
171        a5.save()
172        self.assertEqual(a5.headline, 'Article 6')
173
174        # If you leave off a field with "default" set, Django will use
175        # the default.
176        a6 = Article(pub_date=datetime(2005, 7, 31))
177        a6.save()
178        self.assertEqual(a6.headline, u'Default headline')
179
180        # For DateTimeFields, Django saves as much precision (in seconds)
181        # as you give it.
182        a7 = Article(
183            headline='Article 7',
184            pub_date=datetime(2005, 7, 31, 12, 30),
185        )
186        a7.save()
187        self.assertEqual(Article.objects.get(id__exact=a7.id).pub_date,
188            datetime(2005, 7, 31, 12, 30))
189
190        a8 = Article(
191            headline='Article 8',
192            pub_date=datetime(2005, 7, 31, 12, 30, 45),
193        )
194        a8.save()
195        self.assertEqual(Article.objects.get(id__exact=a8.id).pub_date,
196            datetime(2005, 7, 31, 12, 30, 45))
197
198        # Saving an object again doesn't create a new object -- it just saves
199        # the old one.
200        current_id = a8.id
201        a8.save()
202        self.assertEqual(a8.id, current_id)
203        a8.headline = 'Updated article 8'
204        a8.save()
205        self.assertEqual(a8.id, current_id)
206
207        # Check that != and == operators behave as expecte on instances
208        self.assertTrue(a7 != a8)
209        self.assertFalse(a7 == a8)
210        self.assertEqual(a8, Article.objects.get(id__exact=a8.id))
211
212        self.assertTrue(Article.objects.get(id__exact=a8.id) != Article.objects.get(id__exact=a7.id))
213        self.assertFalse(Article.objects.get(id__exact=a8.id) == Article.objects.get(id__exact=a7.id))
214
215        # You can use 'in' to test for membership...
216        self.assertTrue(a8 in Article.objects.all())
217
218        # ... but there will often be more efficient ways if that is all you need:
219        self.assertTrue(Article.objects.filter(id=a8.id).exists())
220
221        # dates() returns a list of available dates of the given scope for
222        # the given field.
223        self.assertQuerysetEqual(
224            Article.objects.dates('pub_date', 'year'),
225            ["datetime.datetime(2005, 1, 1, 0, 0)"])
226        self.assertQuerysetEqual(
227            Article.objects.dates('pub_date', 'month'),
228            ["datetime.datetime(2005, 7, 1, 0, 0)"])
229        self.assertQuerysetEqual(
230            Article.objects.dates('pub_date', 'day'),
231            ["datetime.datetime(2005, 7, 28, 0, 0)",
232             "datetime.datetime(2005, 7, 29, 0, 0)",
233             "datetime.datetime(2005, 7, 30, 0, 0)",
234             "datetime.datetime(2005, 7, 31, 0, 0)"])
235        self.assertQuerysetEqual(
236            Article.objects.dates('pub_date', 'day', order='ASC'),
237            ["datetime.datetime(2005, 7, 28, 0, 0)",
238             "datetime.datetime(2005, 7, 29, 0, 0)",
239             "datetime.datetime(2005, 7, 30, 0, 0)",
240             "datetime.datetime(2005, 7, 31, 0, 0)"])
241        self.assertQuerysetEqual(
242            Article.objects.dates('pub_date', 'day', order='DESC'),
243            ["datetime.datetime(2005, 7, 31, 0, 0)",
244             "datetime.datetime(2005, 7, 30, 0, 0)",
245             "datetime.datetime(2005, 7, 29, 0, 0)",
246             "datetime.datetime(2005, 7, 28, 0, 0)"])
247
248        # dates() requires valid arguments.
249        self.assertRaisesRegexp(
250            TypeError,
251            "dates\(\) takes at least 3 arguments \(1 given\)",
252            Article.objects.dates,
253        )
254
255        self.assertRaisesRegexp(
256            FieldDoesNotExist,
257            "Article has no field named 'invalid_field'",
258            Article.objects.dates,
259            "invalid_field",
260            "year",
261        )
262
263        self.assertRaisesRegexp(
264            AssertionError,
265            "'kind' must be one of 'year', 'month' or 'day'.",
266            Article.objects.dates,
267            "pub_date",
268            "bad_kind",
269        )
270
271        self.assertRaisesRegexp(
272            AssertionError,
273            "'order' must be either 'ASC' or 'DESC'.",
274            Article.objects.dates,
275            "pub_date",
276            "year",
277            order="bad order",
278        )
279
280        # Use iterator() with dates() to return a generator that lazily
281        # requests each result one at a time, to save memory.
282        dates = []
283        for article in Article.objects.dates('pub_date', 'day', order='DESC').iterator():
284            dates.append(article)
285        self.assertEqual(dates, [
286            datetime(2005, 7, 31, 0, 0),
287            datetime(2005, 7, 30, 0, 0),
288            datetime(2005, 7, 29, 0, 0),
289            datetime(2005, 7, 28, 0, 0)])
290
291        # You can combine queries with & and |.
292        s1 = Article.objects.filter(id__exact=a.id)
293        s2 = Article.objects.filter(id__exact=a2.id)
294        self.assertQuerysetEqual(s1 | s2,
295            ["<Article: Area man programs in Python>",
296             "<Article: Second article>"])
297        self.assertQuerysetEqual(s1 & s2, [])
298
299        # You can get the number of objects like this:
300        self.assertEqual(len(Article.objects.filter(id__exact=a.id)), 1)
301
302        # You can get items using index and slice notation.
303        self.assertEqual(Article.objects.all()[0], a)
304        self.assertQuerysetEqual(Article.objects.all()[1:3],
305            ["<Article: Second article>", "<Article: Third article>"])
306
307        s3 = Article.objects.filter(id__exact=a3.id)
308        self.assertQuerysetEqual((s1 | s2 | s3)[::2],
309            ["<Article: Area man programs in Python>",
310             "<Article: Third article>"])
311
312        # Slicing works with longs.
313        self.assertEqual(Article.objects.all()[0L], a)
314        self.assertQuerysetEqual(Article.objects.all()[1L:3L],
315            ["<Article: Second article>", "<Article: Third article>"])
316        self.assertQuerysetEqual((s1 | s2 | s3)[::2L],
317            ["<Article: Area man programs in Python>",
318             "<Article: Third article>"])
319
320        # And can be mixed with ints.
321        self.assertQuerysetEqual(Article.objects.all()[1:3L],
322            ["<Article: Second article>", "<Article: Third article>"])
323
324        # Slices (without step) are lazy:
325        self.assertQuerysetEqual(Article.objects.all()[0:5].filter(),
326            ["<Article: Area man programs in Python>",
327             "<Article: Second article>",
328             "<Article: Third article>",
329             "<Article: Article 6>",
330             "<Article: Default headline>"])
331
332        # Slicing again works:
333        self.assertQuerysetEqual(Article.objects.all()[0:5][0:2],
334            ["<Article: Area man programs in Python>",
335             "<Article: Second article>"])
336        self.assertQuerysetEqual(Article.objects.all()[0:5][:2],
337            ["<Article: Area man programs in Python>",
338             "<Article: Second article>"])
339        self.assertQuerysetEqual(Article.objects.all()[0:5][4:],
340            ["<Article: Default headline>"])
341        self.assertQuerysetEqual(Article.objects.all()[0:5][5:], [])
342
343        # Some more tests!
344        self.assertQuerysetEqual(Article.objects.all()[2:][0:2],
345            ["<Article: Third article>", "<Article: Article 6>"])
346        self.assertQuerysetEqual(Article.objects.all()[2:][:2],
347            ["<Article: Third article>", "<Article: Article 6>"])
348        self.assertQuerysetEqual(Article.objects.all()[2:][2:3],
349            ["<Article: Default headline>"])
350
351        # Using an offset without a limit is also possible.
352        self.assertQuerysetEqual(Article.objects.all()[5:],
353            ["<Article: Fourth article>",
354             "<Article: Article 7>",
355             "<Article: Updated article 8>"])
356
357        # Also, once you have sliced you can't filter, re-order or combine
358        self.assertRaisesRegexp(
359            AssertionError,
360            "Cannot filter a query once a slice has been taken.",
361            Article.objects.all()[0:5].filter,
362            id=a.id,
363        )
364
365        self.assertRaisesRegexp(
366            AssertionError,
367            "Cannot reorder a query once a slice has been taken.",
368            Article.objects.all()[0:5].order_by,
369            'id',
370        )
371
372        try:
373            Article.objects.all()[0:1] & Article.objects.all()[4:5]
374            self.fail('Should raise an AssertionError')
375        except AssertionError, e:
376            self.assertEqual(str(e), "Cannot combine queries once a slice has been taken.")
377        except Exception, e:
378            self.fail('Should raise an AssertionError, not %s' % e)
379
380        # Negative slices are not supported, due to database constraints.
381        # (hint: inverting your ordering might do what you need).
382        try:
383            Article.objects.all()[-1]
384            self.fail('Should raise an AssertionError')
385        except AssertionError, e:
386            self.assertEqual(str(e), "Negative indexing is not supported.")
387        except Exception, e:
388            self.fail('Should raise an AssertionError, not %s' % e)
389
390        error = None
391        try:
392            Article.objects.all()[0:-5]
393        except Exception, e:
394            error = e
395        self.assertTrue(isinstance(error, AssertionError))
396        self.assertEqual(str(error), "Negative indexing is not supported.")
397
398        # An Article instance doesn't have access to the "objects" attribute.
399        # That's only available on the class.
400        self.assertRaisesRegexp(
401            AttributeError,
402            "Manager isn't accessible via Article instances",
403            getattr,
404            a7,
405            "objects",
406        )
407
408        # Bulk delete test: How many objects before and after the delete?
409        self.assertQuerysetEqual(Article.objects.all(),
410            ["<Article: Area man programs in Python>",
411             "<Article: Second article>",
412             "<Article: Third article>",
413             "<Article: Article 6>",
414             "<Article: Default headline>",
415             "<Article: Fourth article>",
416             "<Article: Article 7>",
417             "<Article: Updated article 8>"])
418        Article.objects.filter(id__lte=a4.id).delete()
419        self.assertQuerysetEqual(Article.objects.all(),
420            ["<Article: Article 6>",
421             "<Article: Default headline>",
422             "<Article: Article 7>",
423             "<Article: Updated article 8>"])
424
425    @skipUnlessDBFeature('supports_microsecond_precision')
426    def test_microsecond_precision(self):
427        # In PostgreSQL, microsecond-level precision is available.
428        a9 = Article(
429            headline='Article 9',
430            pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
431        )
432        a9.save()
433        self.assertEqual(Article.objects.get(pk=a9.pk).pub_date,
434            datetime(2005, 7, 31, 12, 30, 45, 180))
435
436    @skipIfDBFeature('supports_microsecond_precision')
437    def test_microsecond_precision_not_supported(self):
438        # In MySQL, microsecond-level precision isn't available. You'll lose
439        # microsecond-level precision once the data is saved.
440        a9 = Article(
441            headline='Article 9',
442            pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
443        )
444        a9.save()
445        self.assertEqual(Article.objects.get(id__exact=a9.id).pub_date,
446            datetime(2005, 7, 31, 12, 30, 45))
447
448    def test_manually_specify_primary_key(self):
449        # You can manually specify the primary key when creating a new object.
450        a101 = Article(
451            id=101,
452            headline='Article 101',
453            pub_date=datetime(2005, 7, 31, 12, 30, 45),
454        )
455        a101.save()
456        a101 = Article.objects.get(pk=101)
457        self.assertEqual(a101.headline, u'Article 101')
458
459    def test_create_method(self):
460        # You can create saved objects in a single step
461        a10 = Article.objects.create(
462            headline="Article 10",
463            pub_date=datetime(2005, 7, 31, 12, 30, 45),
464        )
465        self.assertEqual(Article.objects.get(headline="Article 10"), a10)
466
467    def test_year_lookup_edge_case(self):
468        # Edge-case test: A year lookup should retrieve all objects in
469        # the given year, including Jan. 1 and Dec. 31.
470        a11 = Article.objects.create(
471            headline='Article 11',
472            pub_date=datetime(2008, 1, 1),
473        )
474        a12 = Article.objects.create(
475            headline='Article 12',
476            pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
477        )
478        self.assertQuerysetEqual(Article.objects.filter(pub_date__year=2008),
479            ["<Article: Article 11>", "<Article: Article 12>"])
480
481    def test_unicode_data(self):
482        # Unicode data works, too.
483        a = Article(
484            headline=u'\u6797\u539f \u3081\u3050\u307f',
485            pub_date=datetime(2005, 7, 28),
486        )
487        a.save()
488        self.assertEqual(Article.objects.get(pk=a.id).headline,
489            u'\u6797\u539f \u3081\u3050\u307f')
490
491    def test_hash_function(self):
492        # Model instances have a hash function, so they can be used in sets
493        # or as dictionary keys. Two models compare as equal if their primary
494        # keys are equal.
495        a10 = Article.objects.create(
496            headline="Article 10",
497            pub_date=datetime(2005, 7, 31, 12, 30, 45),
498        )
499        a11 = Article.objects.create(
500            headline='Article 11',
501            pub_date=datetime(2008, 1, 1),
502        )
503        a12 = Article.objects.create(
504            headline='Article 12',
505            pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
506        )
507
508        s = set([a10, a11, a12])
509        self.assertTrue(Article.objects.get(headline='Article 11') in s)
510
511    def test_extra_method_select_argument_with_dashes_and_values(self):
512        # The 'select' argument to extra() supports names with dashes in
513        # them, as long as you use values().
514        a10 = Article.objects.create(
515            headline="Article 10",
516            pub_date=datetime(2005, 7, 31, 12, 30, 45),
517        )
518        a11 = Article.objects.create(
519            headline='Article 11',
520            pub_date=datetime(2008, 1, 1),
521        )
522        a12 = Article.objects.create(
523            headline='Article 12',
524            pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
525        )
526
527        dicts = Article.objects.filter(
528            pub_date__year=2008).extra(
529                select={'dashed-value': '1'}
530            ).values('headline', 'dashed-value')
531        self.assertEqual([sorted(d.items()) for d in dicts],
532            [[('dashed-value', 1), ('headline', u'Article 11')], [('dashed-value', 1), ('headline', u'Article 12')]])
533
534    def test_extra_method_select_argument_with_dashes(self):
535        # If you use 'select' with extra() and names containing dashes on a
536        # query that's *not* a values() query, those extra 'select' values
537        # will silently be ignored.
538        a10 = Article.objects.create(
539            headline="Article 10",
540            pub_date=datetime(2005, 7, 31, 12, 30, 45),
541        )
542        a11 = Article.objects.create(
543            headline='Article 11',
544            pub_date=datetime(2008, 1, 1),
545        )
546        a12 = Article.objects.create(
547            headline='Article 12',
548            pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
549        )
550
551        articles = Article.objects.filter(
552            pub_date__year=2008).extra(
553                select={'dashed-value': '1', 'undashedvalue': '2'})
554        self.assertEqual(articles[0].undashedvalue, 2)