Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Split tests.basic.ModelTests in several tests; refs #18586.

  • Loading branch information...
commit 7e2c804c9417617934cd731a4537719a1bd8d985 1 parent 77c0a90
@zsoldosp zsoldosp authored timgraham committed
View
476 tests/basic/tests.py
@@ -6,7 +6,7 @@
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db import connections, DEFAULT_DB_ALIAS
from django.db import DatabaseError
-from django.db.models.fields import Field, FieldDoesNotExist
+from django.db.models.fields import Field
from django.db.models.manager import BaseManager
from django.db.models.query import QuerySet, EmptyQuerySet, ValuesListQuerySet, MAX_GET_RESULTS
from django.test import TestCase, TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature
@@ -16,7 +16,167 @@
from .models import Article, SelfRef, ArticleSelectOnSave
+class ModelInstanceCreationTests(TestCase):
+
+ def test_object_is_not_written_to_database_until_save_was_called(self):
+ a = Article(
+ id=None,
+ headline='Area man programs in Python',
+ pub_date=datetime(2005, 7, 28),
+ )
+ self.assertIsNone(a.id)
+ self.assertEquals(Article.objects.all().count(), 0)
+
+ # Save it into the database. You have to call save() explicitly.
+ a.save()
+ self.assertIsNotNone(a.id)
+ self.assertEquals(Article.objects.all().count(), 1)
+
+ def test_can_initialize_model_instance_using_positional_arguments(self):
+ """
+ You can initialize a model instance using positional arguments,
+ which should match the field order as defined in the model.
+ """
+ a = Article(None, 'Second article', datetime(2005, 7, 29))
+ a.save()
+
+ self.assertEqual(a.headline, 'Second article')
+ self.assertEqual(a.pub_date, datetime(2005, 7, 29, 0, 0))
+
+ def test_can_create_instance_using_kwargs(self):
+ a = Article(
+ id=None,
+ headline='Third article',
+ pub_date=datetime(2005, 7, 30),
+ )
+ a.save()
+ self.assertEqual(a.headline, 'Third article')
+ self.assertEqual(a.pub_date, datetime(2005, 7, 30, 0, 0))
+
+ def test_autofields_generate_different_values_for_each_instance(self):
+ a1 = Article.objects.create(headline='First', pub_date=datetime(2005, 7, 30, 0, 0))
+ a2 = Article.objects.create(headline='First', pub_date=datetime(2005, 7, 30, 0, 0))
+ a3 = Article.objects.create(headline='First', pub_date=datetime(2005, 7, 30, 0, 0))
+ self.assertNotEqual(a3.id, a1.id)
+ self.assertNotEqual(a3.id, a2.id)
+
+ def test_can_mix_and_match_position_and_kwargs(self):
+ # You can also mix and match position and keyword arguments, but
+ # be sure not to duplicate field information.
+ a = Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
+ a.save()
+ self.assertEqual(a.headline, 'Fourth article')
+
+ def test_cannot_create_instance_with_invalid_kwargs(self):
+ six.assertRaisesRegex(
+ self,
+ TypeError,
+ "'foo' is an invalid keyword argument for this function",
+ Article,
+ id=None,
+ headline='Some headline',
+ pub_date=datetime(2005, 7, 31),
+ foo='bar',
+ )
+
+ def test_can_leave_off_value_for_autofield_and_it_gets_value_on_save(self):
+ """
+ You can leave off the value for an AutoField when creating an
+ object, because it'll get filled in automatically when you save().
+ """
+ a = Article(headline='Article 5', pub_date=datetime(2005, 7, 31))
+ a.save()
+ self.assertEqual(a.headline, 'Article 5')
+ self.assertNotEqual(a.id, None)
+
+ def test_leaving_off_a_field_with_default_set_the_default_will_be_saved(self):
+ a = Article(pub_date=datetime(2005, 7, 31))
+ a.save()
+ self.assertEqual(a.headline, 'Default headline')
+
+ def test_for_datetimefields_saves_as_much_precision_as_was_given(self):
+ """as much precision in *seconds*"""
+ a1 = Article(
+ headline='Article 7',
+ pub_date=datetime(2005, 7, 31, 12, 30),
+ )
+ a1.save()
+ self.assertEqual(Article.objects.get(id__exact=a1.id).pub_date,
+ datetime(2005, 7, 31, 12, 30))
+
+ a2 = Article(
+ headline='Article 8',
+ pub_date=datetime(2005, 7, 31, 12, 30, 45),
+ )
+ a2.save()
+ self.assertEqual(Article.objects.get(id__exact=a2.id).pub_date,
+ datetime(2005, 7, 31, 12, 30, 45))
+
+ def test_saving_an_object_again_does_not_create_a_new_object(self):
+ a = Article(headline='original', pub_date=datetime(2014, 5, 16))
+ a.save()
+ current_id = a.id
+
+ a.save()
+ self.assertEqual(a.id, current_id)
+
+ a.headline = 'Updated headline'
+ a.save()
+ self.assertEqual(a.id, current_id)
+
+ def test_querysets_checking_for_membership(self):
+ headlines = [
+ 'Area man programs in Python', 'Second article', 'Third article']
+ some_pub_date = datetime(2014, 5, 16, 12, 1)
+ for headline in headlines:
+ Article(headline=headline, pub_date=some_pub_date).save()
+ a = Article(headline='Some headline', pub_date=some_pub_date)
+ a.save()
+
+ # You can use 'in' to test for membership...
+ self.assertTrue(a in Article.objects.all())
+ # ... but there will often be more efficient ways if that is all you need:
+ self.assertTrue(Article.objects.filter(id=a.id).exists())
+
+
class ModelTest(TestCase):
+ def test_objects_attribute_is_only_available_on_the_class_itself(self):
+ six.assertRaisesRegex(
+ self,
+ AttributeError,
+ "Manager isn't accessible via Article instances",
+ getattr,
+ Article(),
+ "objects",
+ )
+ self.assertFalse(hasattr(Article(), 'objects'))
+ self.assertTrue(hasattr(Article, 'objects'))
+
+ def test_queryset_delete_removes_all_items_in_that_queryset(self):
+ headlines = [
+ 'An article', 'Article One', 'Amazing article', 'Boring article']
+ some_pub_date = datetime(2014, 5, 16, 12, 1)
+ for headline in headlines:
+ Article(headline=headline, pub_date=some_pub_date).save()
+ self.assertQuerysetEqual(Article.objects.all().order_by('headline'),
+ ["<Article: Amazing article>",
+ "<Article: An article>",
+ "<Article: Article One>",
+ "<Article: Boring article>"])
+ Article.objects.filter(headline__startswith='A').delete()
+ self.assertQuerysetEqual(Article.objects.all().order_by('headline'),
+ ["<Article: Boring article>"])
+
+ def test_not_equal_and_equal_operators_behave_as_expected_on_instances(self):
+ some_pub_date = datetime(2014, 5, 16, 12, 1)
+ a1 = Article.objects.create(headline='First', pub_date=some_pub_date)
+ a2 = Article.objects.create(headline='Second', pub_date=some_pub_date)
+ self.assertTrue(a1 != a2)
+ self.assertFalse(a1 == a2)
+ self.assertTrue(a1 == Article.objects.get(id__exact=a1.id))
+
+ self.assertTrue(Article.objects.get(id__exact=a1.id) != Article.objects.get(id__exact=a2.id))
+ self.assertFalse(Article.objects.get(id__exact=a2.id) == Article.objects.get(id__exact=a1.id))
def test_lookup(self):
# No articles are in the system yet.
@@ -186,320 +346,6 @@ def test_multiple_objects_max_num_fetched(self):
headline__startswith='Area',
)
- def test_object_creation(self):
- # Create an Article.
- a = Article(
- id=None,
- headline='Area man programs in Python',
- pub_date=datetime(2005, 7, 28),
- )
-
- # Save it into the database. You have to call save() explicitly.
- a.save()
-
- # You can initialize a model instance using positional arguments,
- # which should match the field order as defined in the model.
- a2 = Article(None, 'Second article', datetime(2005, 7, 29))
- a2.save()
-
- self.assertNotEqual(a2.id, a.id)
- self.assertEqual(a2.headline, 'Second article')
- self.assertEqual(a2.pub_date, datetime(2005, 7, 29, 0, 0))
-
- # ...or, you can use keyword arguments.
- a3 = Article(
- id=None,
- headline='Third article',
- pub_date=datetime(2005, 7, 30),
- )
- a3.save()
-
- self.assertNotEqual(a3.id, a.id)
- self.assertNotEqual(a3.id, a2.id)
- self.assertEqual(a3.headline, 'Third article')
- self.assertEqual(a3.pub_date, datetime(2005, 7, 30, 0, 0))
-
- # You can also mix and match position and keyword arguments, but
- # be sure not to duplicate field information.
- a4 = Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
- a4.save()
- self.assertEqual(a4.headline, 'Fourth article')
-
- # Don't use invalid keyword arguments.
- six.assertRaisesRegex(
- self,
- TypeError,
- "'foo' is an invalid keyword argument for this function",
- Article,
- id=None,
- headline='Invalid',
- pub_date=datetime(2005, 7, 31),
- foo='bar',
- )
-
- # You can leave off the value for an AutoField when creating an
- # object, because it'll get filled in automatically when you save().
- a5 = Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
- a5.save()
- self.assertEqual(a5.headline, 'Article 6')
-
- # If you leave off a field with "default" set, Django will use
- # the default.
- a6 = Article(pub_date=datetime(2005, 7, 31))
- a6.save()
- self.assertEqual(a6.headline, 'Default headline')
-
- # For DateTimeFields, Django saves as much precision (in seconds)
- # as you give it.
- a7 = Article(
- headline='Article 7',
- pub_date=datetime(2005, 7, 31, 12, 30),
- )
- a7.save()
- self.assertEqual(Article.objects.get(id__exact=a7.id).pub_date,
- datetime(2005, 7, 31, 12, 30))
-
- a8 = Article(
- headline='Article 8',
- pub_date=datetime(2005, 7, 31, 12, 30, 45),
- )
- a8.save()
- self.assertEqual(Article.objects.get(id__exact=a8.id).pub_date,
- datetime(2005, 7, 31, 12, 30, 45))
-
- # Saving an object again doesn't create a new object -- it just saves
- # the old one.
- current_id = a8.id
- a8.save()
- self.assertEqual(a8.id, current_id)
- a8.headline = 'Updated article 8'
- a8.save()
- self.assertEqual(a8.id, current_id)
-
- # Check that != and == operators behave as expecte on instances
- self.assertTrue(a7 != a8)
- self.assertFalse(a7 == a8)
- self.assertEqual(a8, Article.objects.get(id__exact=a8.id))
-
- self.assertTrue(Article.objects.get(id__exact=a8.id) != Article.objects.get(id__exact=a7.id))
- self.assertFalse(Article.objects.get(id__exact=a8.id) == Article.objects.get(id__exact=a7.id))
-
- # You can use 'in' to test for membership...
- self.assertTrue(a8 in Article.objects.all())
-
- # ... but there will often be more efficient ways if that is all you need:
- self.assertTrue(Article.objects.filter(id=a8.id).exists())
-
- # datetimes() returns a list of available dates of the given scope for
- # the given field.
- self.assertQuerysetEqual(
- Article.objects.datetimes('pub_date', 'year'),
- ["datetime.datetime(2005, 1, 1, 0, 0)"])
- self.assertQuerysetEqual(
- Article.objects.datetimes('pub_date', 'month'),
- ["datetime.datetime(2005, 7, 1, 0, 0)"])
- self.assertQuerysetEqual(
- Article.objects.datetimes('pub_date', 'day'),
- ["datetime.datetime(2005, 7, 28, 0, 0)",
- "datetime.datetime(2005, 7, 29, 0, 0)",
- "datetime.datetime(2005, 7, 30, 0, 0)",
- "datetime.datetime(2005, 7, 31, 0, 0)"])
- self.assertQuerysetEqual(
- Article.objects.datetimes('pub_date', 'day', order='ASC'),
- ["datetime.datetime(2005, 7, 28, 0, 0)",
- "datetime.datetime(2005, 7, 29, 0, 0)",
- "datetime.datetime(2005, 7, 30, 0, 0)",
- "datetime.datetime(2005, 7, 31, 0, 0)"])
- self.assertQuerysetEqual(
- Article.objects.datetimes('pub_date', 'day', order='DESC'),
- ["datetime.datetime(2005, 7, 31, 0, 0)",
- "datetime.datetime(2005, 7, 30, 0, 0)",
- "datetime.datetime(2005, 7, 29, 0, 0)",
- "datetime.datetime(2005, 7, 28, 0, 0)"])
-
- # datetimes() requires valid arguments.
- self.assertRaises(
- TypeError,
- Article.objects.dates,
- )
-
- six.assertRaisesRegex(
- self,
- FieldDoesNotExist,
- "Article has no field named 'invalid_field'",
- Article.objects.dates,
- "invalid_field",
- "year",
- )
-
- six.assertRaisesRegex(
- self,
- AssertionError,
- "'kind' must be one of 'year', 'month' or 'day'.",
- Article.objects.dates,
- "pub_date",
- "bad_kind",
- )
-
- six.assertRaisesRegex(
- self,
- AssertionError,
- "'order' must be either 'ASC' or 'DESC'.",
- Article.objects.dates,
- "pub_date",
- "year",
- order="bad order",
- )
-
- # Use iterator() with datetimes() to return a generator that lazily
- # requests each result one at a time, to save memory.
- dates = []
- for article in Article.objects.datetimes('pub_date', 'day', order='DESC').iterator():
- dates.append(article)
- self.assertEqual(dates, [
- datetime(2005, 7, 31, 0, 0),
- datetime(2005, 7, 30, 0, 0),
- datetime(2005, 7, 29, 0, 0),
- datetime(2005, 7, 28, 0, 0)])
-
- # You can combine queries with & and |.
- s1 = Article.objects.filter(id__exact=a.id)
- s2 = Article.objects.filter(id__exact=a2.id)
- self.assertQuerysetEqual(s1 | s2,
- ["<Article: Area man programs in Python>",
- "<Article: Second article>"])
- self.assertQuerysetEqual(s1 & s2, [])
-
- # You can get the number of objects like this:
- self.assertEqual(len(Article.objects.filter(id__exact=a.id)), 1)
-
- # You can get items using index and slice notation.
- self.assertEqual(Article.objects.all()[0], a)
- self.assertQuerysetEqual(Article.objects.all()[1:3],
- ["<Article: Second article>", "<Article: Third article>"])
-
- s3 = Article.objects.filter(id__exact=a3.id)
- self.assertQuerysetEqual((s1 | s2 | s3)[::2],
- ["<Article: Area man programs in Python>",
- "<Article: Third article>"])
-
- # Slicing works with longs (Python 2 only -- Python 3 doesn't have longs).
- if six.PY2:
- self.assertEqual(Article.objects.all()[long(0)], a)
- self.assertQuerysetEqual(Article.objects.all()[long(1):long(3)],
- ["<Article: Second article>", "<Article: Third article>"])
- self.assertQuerysetEqual((s1 | s2 | s3)[::long(2)],
- ["<Article: Area man programs in Python>",
- "<Article: Third article>"])
-
- # And can be mixed with ints.
- self.assertQuerysetEqual(Article.objects.all()[1:long(3)],
- ["<Article: Second article>", "<Article: Third article>"])
-
- # Slices (without step) are lazy:
- self.assertQuerysetEqual(Article.objects.all()[0:5].filter(),
- ["<Article: Area man programs in Python>",
- "<Article: Second article>",
- "<Article: Third article>",
- "<Article: Article 6>",
- "<Article: Default headline>"])
-
- # Slicing again works:
- self.assertQuerysetEqual(Article.objects.all()[0:5][0:2],
- ["<Article: Area man programs in Python>",
- "<Article: Second article>"])
- self.assertQuerysetEqual(Article.objects.all()[0:5][:2],
- ["<Article: Area man programs in Python>",
- "<Article: Second article>"])
- self.assertQuerysetEqual(Article.objects.all()[0:5][4:],
- ["<Article: Default headline>"])
- self.assertQuerysetEqual(Article.objects.all()[0:5][5:], [])
-
- # Some more tests!
- self.assertQuerysetEqual(Article.objects.all()[2:][0:2],
- ["<Article: Third article>", "<Article: Article 6>"])
- self.assertQuerysetEqual(Article.objects.all()[2:][:2],
- ["<Article: Third article>", "<Article: Article 6>"])
- self.assertQuerysetEqual(Article.objects.all()[2:][2:3],
- ["<Article: Default headline>"])
-
- # Using an offset without a limit is also possible.
- self.assertQuerysetEqual(Article.objects.all()[5:],
- ["<Article: Fourth article>",
- "<Article: Article 7>",
- "<Article: Updated article 8>"])
-
- # Also, once you have sliced you can't filter, re-order or combine
- six.assertRaisesRegex(
- self,
- AssertionError,
- "Cannot filter a query once a slice has been taken.",
- Article.objects.all()[0:5].filter,
- id=a.id,
- )
-
- six.assertRaisesRegex(
- self,
- AssertionError,
- "Cannot reorder a query once a slice has been taken.",
- Article.objects.all()[0:5].order_by,
- 'id',
- )
-
- try:
- Article.objects.all()[0:1] & Article.objects.all()[4:5]
- self.fail('Should raise an AssertionError')
- except AssertionError as e:
- self.assertEqual(str(e), "Cannot combine queries once a slice has been taken.")
- except Exception as e:
- self.fail('Should raise an AssertionError, not %s' % e)
-
- # Negative slices are not supported, due to database constraints.
- # (hint: inverting your ordering might do what you need).
- try:
- Article.objects.all()[-1]
- self.fail('Should raise an AssertionError')
- except AssertionError as e:
- self.assertEqual(str(e), "Negative indexing is not supported.")
- except Exception as e:
- self.fail('Should raise an AssertionError, not %s' % e)
-
- error = None
- try:
- Article.objects.all()[0:-5]
- except Exception as e:
- error = e
- self.assertIsInstance(error, AssertionError)
- self.assertEqual(str(error), "Negative indexing is not supported.")
-
- # An Article instance doesn't have access to the "objects" attribute.
- # That's only available on the class.
- six.assertRaisesRegex(
- self,
- AttributeError,
- "Manager isn't accessible via Article instances",
- getattr,
- a7,
- "objects",
- )
-
- # Bulk delete test: How many objects before and after the delete?
- self.assertQuerysetEqual(Article.objects.all(),
- ["<Article: Area man programs in Python>",
- "<Article: Second article>",
- "<Article: Third article>",
- "<Article: Article 6>",
- "<Article: Default headline>",
- "<Article: Fourth article>",
- "<Article: Article 7>",
- "<Article: Updated article 8>"])
- Article.objects.filter(id__lte=a4.id).delete()
- self.assertQuerysetEqual(Article.objects.all(),
- ["<Article: Article 6>",
- "<Article: Default headline>",
- "<Article: Article 7>",
- "<Article: Updated article 8>"])
-
@skipUnlessDBFeature('supports_microsecond_precision')
def test_microsecond_precision(self):
# In PostgreSQL, microsecond-level precision is available.
View
39 tests/dates/tests.py
@@ -2,7 +2,9 @@
import datetime
+from django.db.models.fields import FieldDoesNotExist
from django.test import TestCase
+from django.utils import six
from .models import Article, Comment, Category
@@ -81,3 +83,40 @@ def test_related_model_traverse(self):
],
lambda d: d,
)
+
+ def test_dates_fails_when_no_arguments_are_provided(self):
+ self.assertRaises(
+ TypeError,
+ Article.objects.dates,
+ )
+
+ def test_dates_fails_when_given_invalid_field_argument(self):
+ six.assertRaisesRegex(
+ self,
+ FieldDoesNotExist,
+ "Article has no field named 'invalid_field'",
+ Article.objects.dates,
+ "invalid_field",
+ "year",
+ )
+
+ def test_dates_fails_when_given_invalid_kind_argument(self):
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "'kind' must be one of 'year', 'month' or 'day'.",
+ Article.objects.dates,
+ "pub_date",
+ "bad_kind",
+ )
+
+ def test_dates_fails_when_given_invalid_order_argument(self):
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "'order' must be either 'ASC' or 'DESC'.",
+ Article.objects.dates,
+ "pub_date",
+ "year",
+ order="bad order",
+ )
View
57 tests/datetimes/tests.py
@@ -97,3 +97,60 @@ def test_21432(self):
Article.objects.create(title="First one", pub_date=now)
qs = Article.objects.datetimes('pub_date', 'second')
self.assertEqual(qs[0], now)
+
+ def test_datetimes_returns_available_dates_for_given_scope_and_given_field(self):
+ pub_dates = [
+ datetime.datetime(2005, 7, 28, 12, 15),
+ datetime.datetime(2005, 7, 29, 2, 15),
+ datetime.datetime(2005, 7, 30, 5, 15),
+ datetime.datetime(2005, 7, 31, 19, 15)]
+ for i, pub_date in enumerate(pub_dates):
+ Article(pub_date=pub_date, title='title #{}'.format(i)).save()
+
+ self.assertQuerysetEqual(
+ Article.objects.datetimes('pub_date', 'year'),
+ ["datetime.datetime(2005, 1, 1, 0, 0)"])
+ self.assertQuerysetEqual(
+ Article.objects.datetimes('pub_date', 'month'),
+ ["datetime.datetime(2005, 7, 1, 0, 0)"])
+ self.assertQuerysetEqual(
+ Article.objects.datetimes('pub_date', 'day'),
+ ["datetime.datetime(2005, 7, 28, 0, 0)",
+ "datetime.datetime(2005, 7, 29, 0, 0)",
+ "datetime.datetime(2005, 7, 30, 0, 0)",
+ "datetime.datetime(2005, 7, 31, 0, 0)"])
+ self.assertQuerysetEqual(
+ Article.objects.datetimes('pub_date', 'day', order='ASC'),
+ ["datetime.datetime(2005, 7, 28, 0, 0)",
+ "datetime.datetime(2005, 7, 29, 0, 0)",
+ "datetime.datetime(2005, 7, 30, 0, 0)",
+ "datetime.datetime(2005, 7, 31, 0, 0)"])
+ self.assertQuerysetEqual(
+ Article.objects.datetimes('pub_date', 'day', order='DESC'),
+ ["datetime.datetime(2005, 7, 31, 0, 0)",
+ "datetime.datetime(2005, 7, 30, 0, 0)",
+ "datetime.datetime(2005, 7, 29, 0, 0)",
+ "datetime.datetime(2005, 7, 28, 0, 0)"])
+
+ def test_datetimes_has_lazy_iterator(self):
+ pub_dates = [
+ datetime.datetime(2005, 7, 28, 12, 15),
+ datetime.datetime(2005, 7, 29, 2, 15),
+ datetime.datetime(2005, 7, 30, 5, 15),
+ datetime.datetime(2005, 7, 31, 19, 15)]
+ for i, pub_date in enumerate(pub_dates):
+ Article(pub_date=pub_date, title='title #{}'.format(i)).save()
+ # Use iterator() with datetimes() to return a generator that lazily
+ # requests each result one at a time, to save memory.
+ dates = []
+ with self.assertNumQueries(0):
+ article_datetimes_iterator = Article.objects.datetimes('pub_date', 'day', order='DESC').iterator()
+
+ with self.assertNumQueries(1):
+ for article in article_datetimes_iterator:
+ dates.append(article)
+ self.assertEqual(dates, [
+ datetime.datetime(2005, 7, 31, 0, 0),
+ datetime.datetime(2005, 7, 30, 0, 0),
+ datetime.datetime(2005, 7, 29, 0, 0),
+ datetime.datetime(2005, 7, 28, 0, 0)])
View
4 tests/queries/models.py
@@ -364,10 +364,14 @@ def __str__(self):
return self.name
+@python_2_unicode_compatible
class Article(models.Model):
name = models.CharField(max_length=20)
created = models.DateTimeField()
+ def __str__(self):
+ return self.name
+
@python_2_unicode_compatible
class Food(models.Model):
View
123 tests/queries/tests.py
@@ -2145,6 +2145,129 @@ def test_flat_extra_values_list(self):
self.assertQuerysetEqual(qs, [72], self.identity)
+class QuerySetSupportsPythonIdioms(TestCase):
+
+ def setUp(self):
+ some_date = datetime.datetime(2014, 5, 16, 12, 1)
+ for i in range(1, 8):
+ Article.objects.create(
+ name="Article {}".format(i), created=some_date)
+
+ def get_ordered_articles(self):
+ return Article.objects.all().order_by('name')
+
+ def test_can_get_items_using_index_and_slice_notation(self):
+ self.assertEqual(self.get_ordered_articles()[0].name, 'Article 1')
+ self.assertQuerysetEqual(self.get_ordered_articles()[1:3],
+ ["<Article: Article 2>", "<Article: Article 3>"])
+
+ def test_slicing_with_steps_can_be_used(self):
+ self.assertQuerysetEqual(self.get_ordered_articles()[::2],
+ ["<Article: Article 1>",
+ "<Article: Article 3>",
+ "<Article: Article 5>",
+ "<Article: Article 7>"])
+
+ @unittest.skipUnless(six.PY2, "Python 2 only -- Python 3 doesn't have longs.")
+ def test_slicing_works_with_longs(self):
+ self.assertEqual(self.get_ordered_articles()[long(0)].name, 'Article 1')
+ self.assertQuerysetEqual(self.get_ordered_articles()[long(1):long(3)],
+ ["<Article: Article 2>", "<Article: Article 3>"])
+ self.assertQuerysetEqual(self.get_ordered_articles()[::long(2)],
+ ["<Article: Article 1>",
+ "<Article: Article 3>",
+ "<Article: Article 5>",
+ "<Article: Article 7>"])
+
+ # And can be mixed with ints.
+ self.assertQuerysetEqual(self.get_ordered_articles()[1:long(3)],
+ ["<Article: Article 2>", "<Article: Article 3>"])
+
+ def test_slicing_without_step_is_lazy(self):
+ with self.assertNumQueries(0):
+ self.get_ordered_articles()[0:5]
+
+ def test_slicing_with_tests_is_not_lazy(self):
+ with self.assertNumQueries(1):
+ self.get_ordered_articles()[0:5:3]
+
+ def test_slicing_can_slice_again_after_slicing(self):
+ self.assertQuerysetEqual(self.get_ordered_articles()[0:5][0:2],
+ ["<Article: Article 1>",
+ "<Article: Article 2>"])
+ self.assertQuerysetEqual(self.get_ordered_articles()[0:5][4:],
+ ["<Article: Article 5>"])
+ self.assertQuerysetEqual(self.get_ordered_articles()[0:5][5:], [])
+
+ # Some more tests!
+ self.assertQuerysetEqual(self.get_ordered_articles()[2:][0:2],
+ ["<Article: Article 3>", "<Article: Article 4>"])
+ self.assertQuerysetEqual(self.get_ordered_articles()[2:][:2],
+ ["<Article: Article 3>", "<Article: Article 4>"])
+ self.assertQuerysetEqual(self.get_ordered_articles()[2:][2:3],
+ ["<Article: Article 5>"])
+
+ # Using an offset without a limit is also possible.
+ self.assertQuerysetEqual(self.get_ordered_articles()[5:],
+ ["<Article: Article 6>",
+ "<Article: Article 7>"])
+
+ def test_slicing_cannot_filter_queryset_once_sliced(self):
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "Cannot filter a query once a slice has been taken.",
+ Article.objects.all()[0:5].filter,
+ id=1,
+ )
+
+ def test_slicing_cannot_reorder_queryset_once_sliced(self):
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "Cannot reorder a query once a slice has been taken.",
+ Article.objects.all()[0:5].order_by,
+ 'id',
+ )
+
+ def test_slicing_cannot_combine_queries_once_sliced(self):
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "Cannot combine queries once a slice has been taken.",
+ lambda: Article.objects.all()[0:1] & Article.objects.all()[4:5]
+ )
+
+ def test_slicing_negative_indexing_not_supported_for_single_element(self):
+ """hint: inverting your ordering might do what you need"""
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "Negative indexing is not supported.",
+ lambda: Article.objects.all()[-1]
+ )
+
+ def test_slicing_negative_indexing_not_supported_for_range(self):
+ """hint: inverting your ordering might do what you need"""
+ six.assertRaisesRegex(
+ self,
+ AssertionError,
+ "Negative indexing is not supported.",
+ lambda: Article.objects.all()[0:-5]
+ )
+
+ def test_can_get_number_of_items_in_queryset_using_standard_len(self):
+ self.assertEqual(len(Article.objects.filter(name__exact='Article 1')), 1)
+
+ def test_can_combine_queries_using_and_and_or_operators(self):
+ s1 = Article.objects.filter(name__exact='Article 1')
+ s2 = Article.objects.filter(name__exact='Article 2')
+ self.assertQuerysetEqual((s1 | s2).order_by('name'),
+ ["<Article: Article 1>",
+ "<Article: Article 2>"])
+ self.assertQuerysetEqual(s1 & s2, [])
+
+
class WeirdQuerysetSlicingTests(BaseQuerysetTest):
def setUp(self):
Number.objects.create(num=1)
Please sign in to comment.
Something went wrong with that request. Please try again.