diff --git a/docs/userguide.rst b/docs/userguide.rst index 602d51b6..405f7418 100644 --- a/docs/userguide.rst +++ b/docs/userguide.rst @@ -183,6 +183,41 @@ sign. Note that direction only matters on multi-field indexes. :: meta = { 'indexes': ['title', ('title', '-rating')] } + +Ordering +-------- + +A default ordering can be specified for your :class:`~mongoengine.queryset.QuerySet` +using the :attr:`ordering` attributeof :attr:`~Document.meta`. +Ordering will be applied when the ``QuerySet`` is created, and can be +overridden by subsequent calls to :meth:`~mongoengine.QuerySet.order_by`. :: + + from datetime import datetime + + class BlogPost(Document): + title = StringField() + published_date = DateTimeField() + + meta = { + 'ordering': ['-published_date'] + } + + blog_post_1 = BlogPost(title="Blog Post #1", published_date=datetime(2010, 1, 5, 0, 0 ,0)) + blog_post_2 = BlogPost(title="Blog Post #2", published_date=datetime(2010, 1, 6, 0, 0 ,0)) + blog_post_3 = BlogPost(title="Blog Post #3", published_date=datetime(2010, 1, 7, 0, 0 ,0)) + + blog_post_1.save() + blog_post_2.save() + blog_post_3.save() + + # get the "first" BlogPost using default ordering + # from BlogPost.meta.ordering + latest_post = BlogPost.objects.first() + self.assertEqual(latest_post.title, "Blog Post #3") + + # override default ordering, order BlogPosts by "published_date" + first_post = BlogPost.objects.order_by("+published_date").first() + self.assertEqual(first_post.title, "Blog Post #1") Document inheritance -------------------- diff --git a/mongoengine/base.py b/mongoengine/base.py index 8a423a3e..f930f06c 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -155,6 +155,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass): 'allow_inheritance': True, 'max_documents': None, 'max_size': None, + 'ordering': [], # default ordering applied at runtime 'indexes': [] # indexes to be ensured at runtime } diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 761a9003..836d847a 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -59,7 +59,6 @@ class QuerySet(object): # ensure document-defined indexes are created if self._document._meta['indexes']: for key_or_list in self._document._meta['indexes']: - # print "key", key_or_list self.ensure_index(key_or_list) query = QuerySet._transform_query(_doc_cls=self._document, **query) @@ -70,6 +69,11 @@ class QuerySet(object): def _cursor(self): if not self._cursor_obj: self._cursor_obj = self._collection.find(self._query) + + # apply default ordering + if self._document._meta['ordering']: + self.order_by(*self._document._meta['ordering']) + return self._cursor_obj @classmethod diff --git a/tests/queryset.py b/tests/queryset.py index e7e79ccc..f1ba9841 100644 --- a/tests/queryset.py +++ b/tests/queryset.py @@ -131,6 +131,36 @@ class QuerySetTest(unittest.TestCase): person = self.Person.objects.with_id(person1.id) self.assertEqual(person.name, "User A") + def test_ordering(self): + """Ensure default ordering is applied and can be overridden. + """ + from datetime import datetime + + class BlogPost(Document): + title = StringField() + published_date = DateTimeField() + + meta = { + 'ordering': ['-published_date'] + } + + blog_post_1 = BlogPost(title="Blog Post #1", published_date=datetime(2010, 1, 5, 0, 0 ,0)) + blog_post_2 = BlogPost(title="Blog Post #2", published_date=datetime(2010, 1, 6, 0, 0 ,0)) + blog_post_3 = BlogPost(title="Blog Post #3", published_date=datetime(2010, 1, 7, 0, 0 ,0)) + + blog_post_1.save() + blog_post_2.save() + blog_post_3.save() + + # get the "first" BlogPost using default ordering + # from BlogPost.meta.ordering + latest_post = BlogPost.objects.first() + self.assertEqual(latest_post.title, "Blog Post #3") + + # override default ordering, order BlogPosts by "published_date" + first_post = BlogPost.objects.order_by("+published_date").first() + self.assertEqual(first_post.title, "Blog Post #1") + def test_find_embedded(self): """Ensure that an embedded document is properly returned from a query. """