diff --git a/docs/changelog.rst b/docs/changelog.rst index 95272ba3..5c3b02d0 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog Changes in 0.8.5 ================ +- Fixed distinct casting issue with ListField of EmbeddedDocuments (#470) - Fixed Django 1.6 sessions (#454, #480) Changes in 0.8.4 diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index ad75eccb..c7fe276c 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -621,8 +621,15 @@ class BaseQuerySet(object): try: field = self._fields_to_dbfields([field]).pop() finally: - return self._dereference(queryset._cursor.distinct(field), 1, - name=field, instance=self._document) + distinct = self._dereference(queryset._cursor.distinct(field), 1, + name=field, instance=self._document) + + # We may need to cast to the correct type eg. ListField(EmbeddedDocumentField) + doc_field = getattr(self._document._fields.get(field), "field", None) + instance = getattr(doc_field, "document_type", False) + if instance: + distinct = [instance(**doc) for doc in distinct] + return distinct def only(self, *fields): """Load only a subset of this document's fields. :: diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index b4bcf2a7..4b2ec6b4 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -2519,6 +2519,27 @@ class QuerySetTest(unittest.TestCase): Product.drop_collection() + def test_distinct_ListField_EmbeddedDocumentField(self): + + class Author(EmbeddedDocument): + name = StringField() + + class Book(Document): + title = StringField() + authors = ListField(EmbeddedDocumentField(Author)) + + Book.drop_collection() + + mark_twain = Author(name="Mark Twain") + john_tolkien = Author(name="John Ronald Reuel Tolkien") + + book = Book(title="Tom Sawyer", authors=[mark_twain]).save() + book = Book(title="The Lord of the Rings", authors=[john_tolkien]).save() + book = Book(title="The Stories", authors=[mark_twain, john_tolkien]).save() + authors = Book.objects.distinct("authors") + + self.assertEquals(authors, [mark_twain, john_tolkien]) + def test_custom_manager(self): """Ensure that custom QuerySetManager instances work as expected. """