Merge branch 'master' into dev
Conflicts: mongoengine/queryset.py
This commit is contained in:
		
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -115,3 +115,4 @@ that much better: | |||||||
|  * Alexandre González |  * Alexandre González | ||||||
|  * Thomas Steinacher |  * Thomas Steinacher | ||||||
|  * Tommi Komulainen |  * Tommi Komulainen | ||||||
|  |  * Peter Landry | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| MongoEngine | MongoEngine | ||||||
| =========== | =========== | ||||||
| :Info: MongoEngine is an ORM-like layer on top of PyMongo. | :Info: MongoEngine is an ORM-like layer on top of PyMongo. | ||||||
|  | :Repository: https://github.com/MongoEngine/mongoengine | ||||||
| :Author: Harry Marr (http://github.com/hmarr) | :Author: Harry Marr (http://github.com/hmarr) | ||||||
| :Maintainer: Ross Lawley (http://github.com/rozza) | :Maintainer: Ross Lawley (http://github.com/rozza) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,8 +2,14 @@ | |||||||
| Changelog | Changelog | ||||||
| ========= | ========= | ||||||
|  |  | ||||||
| Changes in 0.6.X | Changes in 0.6.20 | ||||||
| ================ | ================= | ||||||
|  | - Added support for distinct and db_alias (MongoEngine/mongoengine#59) | ||||||
|  | - Improved support for chained querysets when constraining the same fields (hmarr/mongoengine#554) | ||||||
|  | - Fixed BinaryField lookup re (MongoEngine/mongoengine#48) | ||||||
|  |  | ||||||
|  | Changes in 0.6.19 | ||||||
|  | ================= | ||||||
|  |  | ||||||
| - Added Binary support to UUID (MongoEngine/mongoengine#47) | - Added Binary support to UUID (MongoEngine/mongoengine#47) | ||||||
| - Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46) | - Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46) | ||||||
|   | |||||||
| @@ -232,7 +232,7 @@ custom manager methods as you like:: | |||||||
|     BlogPost(title='test1', published=False).save() |     BlogPost(title='test1', published=False).save() | ||||||
|     BlogPost(title='test2', published=True).save() |     BlogPost(title='test2', published=True).save() | ||||||
|     assert len(BlogPost.objects) == 2 |     assert len(BlogPost.objects) == 2 | ||||||
|     assert len(BlogPost.live_posts) == 1 |     assert len(BlogPost.live_posts()) == 1 | ||||||
|  |  | ||||||
| Custom QuerySets | Custom QuerySets | ||||||
| ================ | ================ | ||||||
| @@ -243,11 +243,16 @@ a document, set ``queryset_class`` to the custom class in a | |||||||
| :class:`~mongoengine.Document`\ s ``meta`` dictionary:: | :class:`~mongoengine.Document`\ s ``meta`` dictionary:: | ||||||
|  |  | ||||||
|     class AwesomerQuerySet(QuerySet): |     class AwesomerQuerySet(QuerySet): | ||||||
|         pass |  | ||||||
|  |         def get_awesome(self): | ||||||
|  |             return self.filter(awesome=True) | ||||||
|  |  | ||||||
|     class Page(Document): |     class Page(Document): | ||||||
|         meta = {'queryset_class': AwesomerQuerySet} |         meta = {'queryset_class': AwesomerQuerySet} | ||||||
|  |  | ||||||
|  |     # To call: | ||||||
|  |     Page.objects.get_awesome() | ||||||
|  |  | ||||||
| .. versionadded:: 0.4 | .. versionadded:: 0.4 | ||||||
|  |  | ||||||
| Aggregation | Aggregation | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ from signals import * | |||||||
| __all__ = (document.__all__ + fields.__all__ + connection.__all__ + | __all__ = (document.__all__ + fields.__all__ + connection.__all__ + | ||||||
|            queryset.__all__ + signals.__all__) |            queryset.__all__ + signals.__all__) | ||||||
|  |  | ||||||
| VERSION = (0, 6, 18) | VERSION = (0, 6, 20) | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_version(): | def get_version(): | ||||||
|   | |||||||
| @@ -34,7 +34,9 @@ class DeReference(object): | |||||||
|  |  | ||||||
|         doc_type = None |         doc_type = None | ||||||
|         if instance and instance._fields: |         if instance and instance._fields: | ||||||
|             doc_type = instance._fields[name].field |             doc_type = instance._fields[name] | ||||||
|  |             if hasattr(doc_type, 'field'): | ||||||
|  |                 doc_type = doc_type.field | ||||||
|  |  | ||||||
|             if isinstance(doc_type, ReferenceField): |             if isinstance(doc_type, ReferenceField): | ||||||
|                 doc_type = doc_type.document_type |                 doc_type = doc_type.document_type | ||||||
|   | |||||||
| @@ -1327,7 +1327,7 @@ class UUIDField(BaseField): | |||||||
|         super(UUIDField, self).__init__(**kwargs) |         super(UUIDField, self).__init__(**kwargs) | ||||||
|  |  | ||||||
|     def to_python(self, value): |     def to_python(self, value): | ||||||
|         if not self.binary: |         if not self._binary: | ||||||
|             if not isinstance(value, basestring): |             if not isinstance(value, basestring): | ||||||
|                 value = unicode(value) |                 value = unicode(value) | ||||||
|             return uuid.UUID(value) |             return uuid.UUID(value) | ||||||
|   | |||||||
| @@ -765,8 +765,22 @@ class QuerySet(object): | |||||||
|             key = '.'.join(parts) |             key = '.'.join(parts) | ||||||
|             if op is None or key not in mongo_query: |             if op is None or key not in mongo_query: | ||||||
|                 mongo_query[key] = value |                 mongo_query[key] = value | ||||||
|             elif key in mongo_query and isinstance(mongo_query[key], dict): |             elif key in mongo_query: | ||||||
|  |                 if isinstance(mongo_query[key], dict) and isinstance(value, dict): | ||||||
|                     mongo_query[key].update(value) |                     mongo_query[key].update(value) | ||||||
|  |                 elif isinstance(mongo_query[key], list): | ||||||
|  |                     mongo_query[key].append(value) | ||||||
|  |                 else: | ||||||
|  |                     mongo_query[key] = [mongo_query[key], value] | ||||||
|  |  | ||||||
|  |         for k, v in mongo_query.items(): | ||||||
|  |             if isinstance(v, list): | ||||||
|  |                 value = [{k:val} for val in v] | ||||||
|  |                 if '$and' in mongo_query.keys(): | ||||||
|  |                     mongo_query['$and'].append(value) | ||||||
|  |                 else: | ||||||
|  |                     mongo_query['$and'] = value | ||||||
|  |                 del mongo_query[k] | ||||||
|  |  | ||||||
|         return mongo_query |         return mongo_query | ||||||
|  |  | ||||||
| @@ -1152,8 +1166,10 @@ class QuerySet(object): | |||||||
|  |  | ||||||
|         .. versionadded:: 0.4 |         .. versionadded:: 0.4 | ||||||
|         .. versionchanged:: 0.5 - Fixed handling references |         .. versionchanged:: 0.5 - Fixed handling references | ||||||
|  |         .. versionchanged:: 0.6 - Improved db_field refrence handling | ||||||
|         """ |         """ | ||||||
|         return self._dereference(self._cursor.distinct(field), 1) |         return self._dereference(self._cursor.distinct(field), 1, | ||||||
|  |                                  name=field, instance=self._document) | ||||||
|  |  | ||||||
|     def only(self, *fields): |     def only(self, *fields): | ||||||
|         """Load only a subset of this document's fields. :: |         """Load only a subset of this document's fields. :: | ||||||
| @@ -1866,6 +1882,17 @@ class QuerySet(object): | |||||||
|  |  | ||||||
|  |  | ||||||
| class QuerySetManager(object): | class QuerySetManager(object): | ||||||
|  |     """ | ||||||
|  |     The default QuerySet Manager. | ||||||
|  |  | ||||||
|  |     Custom QuerySet Manager functions can extend this class and users can | ||||||
|  |     add extra queryset functionality.  Any custom manager methods must accept a | ||||||
|  |     :class:`~mongoengine.Document` class as its first argument, and a | ||||||
|  |     :class:`~mongoengine.queryset.QuerySet` as its second argument. | ||||||
|  |  | ||||||
|  |     The method function should return a :class:`~mongoengine.queryset.QuerySet` | ||||||
|  |     , probably the same one that was passed in, but modified in some way. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|     get_queryset = None |     get_queryset = None | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| %define srcname mongoengine | %define srcname mongoengine | ||||||
|  |  | ||||||
| Name:           python-%{srcname} | Name:           python-%{srcname} | ||||||
| Version:        0.6.18 | Version:        0.6.20 | ||||||
| Release:        1%{?dist} | Release:        1%{?dist} | ||||||
| Summary:        A Python Document-Object Mapper for working with MongoDB | Summary:        A Python Document-Object Mapper for working with MongoDB | ||||||
|  |  | ||||||
|   | |||||||
| @@ -283,6 +283,7 @@ class FieldTest(unittest.TestCase): | |||||||
|         uu = uuid.uuid4() |         uu = uuid.uuid4() | ||||||
|         Person(api_key=uu).save() |         Person(api_key=uu).save() | ||||||
|         self.assertEqual(1, Person.objects(api_key=uu).count()) |         self.assertEqual(1, Person.objects(api_key=uu).count()) | ||||||
|  |         self.assertEqual(uu, Person.objects.first().api_key) | ||||||
|  |  | ||||||
|         person = Person() |         person = Person() | ||||||
|         valid = (uuid.uuid4(), uuid.uuid1()) |         valid = (uuid.uuid4(), uuid.uuid1()) | ||||||
| @@ -307,6 +308,7 @@ class FieldTest(unittest.TestCase): | |||||||
|         uu = uuid.uuid4() |         uu = uuid.uuid4() | ||||||
|         Person(api_key=uu).save() |         Person(api_key=uu).save() | ||||||
|         self.assertEqual(1, Person.objects(api_key=uu).count()) |         self.assertEqual(1, Person.objects(api_key=uu).count()) | ||||||
|  |         self.assertEqual(uu, Person.objects.first().api_key) | ||||||
|  |  | ||||||
|         person = Person() |         person = Person() | ||||||
|         valid = (uuid.uuid4(), uuid.uuid1()) |         valid = (uuid.uuid4(), uuid.uuid1()) | ||||||
|   | |||||||
| @@ -827,7 +827,11 @@ class QuerySetTest(unittest.TestCase): | |||||||
|     def test_filter_chaining(self): |     def test_filter_chaining(self): | ||||||
|         """Ensure filters can be chained together. |         """Ensure filters can be chained together. | ||||||
|         """ |         """ | ||||||
|  |         class Blog(Document): | ||||||
|  |             id = StringField(unique=True, primary_key=True) | ||||||
|  |  | ||||||
|         class BlogPost(Document): |         class BlogPost(Document): | ||||||
|  |             blog = ReferenceField(Blog) | ||||||
|             title = StringField() |             title = StringField() | ||||||
|             is_published = BooleanField() |             is_published = BooleanField() | ||||||
|             published_date = DateTimeField() |             published_date = DateTimeField() | ||||||
| @@ -836,13 +840,24 @@ class QuerySetTest(unittest.TestCase): | |||||||
|             def published(doc_cls, queryset): |             def published(doc_cls, queryset): | ||||||
|                 return queryset(is_published=True) |                 return queryset(is_published=True) | ||||||
|  |  | ||||||
|         blog_post_1 = BlogPost(title="Blog Post #1", |         Blog.drop_collection() | ||||||
|  |         BlogPost.drop_collection() | ||||||
|  |  | ||||||
|  |         blog_1 = Blog(id="1") | ||||||
|  |         blog_2 = Blog(id="2") | ||||||
|  |         blog_3 = Blog(id="3") | ||||||
|  |  | ||||||
|  |         blog_1.save() | ||||||
|  |         blog_2.save() | ||||||
|  |         blog_3.save() | ||||||
|  |  | ||||||
|  |         blog_post_1 = BlogPost(blog=blog_1, title="Blog Post #1", | ||||||
|                                is_published = True, |                                is_published = True, | ||||||
|                                published_date=datetime(2010, 1, 5, 0, 0 ,0)) |                                published_date=datetime(2010, 1, 5, 0, 0 ,0)) | ||||||
|         blog_post_2 = BlogPost(title="Blog Post #2", |         blog_post_2 = BlogPost(blog=blog_2, title="Blog Post #2", | ||||||
|                                is_published = True, |                                is_published = True, | ||||||
|                                published_date=datetime(2010, 1, 6, 0, 0 ,0)) |                                published_date=datetime(2010, 1, 6, 0, 0 ,0)) | ||||||
|         blog_post_3 = BlogPost(title="Blog Post #3", |         blog_post_3 = BlogPost(blog=blog_3, title="Blog Post #3", | ||||||
|                                is_published = True, |                                is_published = True, | ||||||
|                                published_date=datetime(2010, 1, 7, 0, 0 ,0)) |                                published_date=datetime(2010, 1, 7, 0, 0 ,0)) | ||||||
|  |  | ||||||
| @@ -856,7 +871,14 @@ class QuerySetTest(unittest.TestCase): | |||||||
|             published_date__lt=datetime(2010, 1, 7, 0, 0 ,0)) |             published_date__lt=datetime(2010, 1, 7, 0, 0 ,0)) | ||||||
|         self.assertEqual(published_posts.count(), 2) |         self.assertEqual(published_posts.count(), 2) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         blog_posts = BlogPost.objects | ||||||
|  |         blog_posts = blog_posts.filter(blog__in=[blog_1, blog_2]) | ||||||
|  |         blog_posts = blog_posts.filter(blog=blog_3) | ||||||
|  |         self.assertEqual(blog_posts.count(), 0) | ||||||
|  |  | ||||||
|         BlogPost.drop_collection() |         BlogPost.drop_collection() | ||||||
|  |         Blog.drop_collection() | ||||||
|  |  | ||||||
|     def test_ordering(self): |     def test_ordering(self): | ||||||
|         """Ensure default ordering is applied and can be overridden. |         """Ensure default ordering is applied and can be overridden. | ||||||
| @@ -2277,6 +2299,28 @@ class QuerySetTest(unittest.TestCase): | |||||||
|  |  | ||||||
|         self.assertEquals(Foo.objects.distinct("bar"), [bar]) |         self.assertEquals(Foo.objects.distinct("bar"), [bar]) | ||||||
|  |  | ||||||
|  |     def test_distinct_handles_references_to_alias(self): | ||||||
|  |         register_connection('testdb', 'mongoenginetest2') | ||||||
|  |  | ||||||
|  |         class Foo(Document): | ||||||
|  |             bar = ReferenceField("Bar") | ||||||
|  |             meta = {'db_alias': 'testdb'} | ||||||
|  |  | ||||||
|  |         class Bar(Document): | ||||||
|  |             text = StringField() | ||||||
|  |             meta = {'db_alias': 'testdb'} | ||||||
|  |  | ||||||
|  |         Bar.drop_collection() | ||||||
|  |         Foo.drop_collection() | ||||||
|  |  | ||||||
|  |         bar = Bar(text="hi") | ||||||
|  |         bar.save() | ||||||
|  |  | ||||||
|  |         foo = Foo(bar=bar) | ||||||
|  |         foo.save() | ||||||
|  |  | ||||||
|  |         self.assertEquals(Foo.objects.distinct("bar"), [bar]) | ||||||
|  |  | ||||||
|     def test_custom_manager(self): |     def test_custom_manager(self): | ||||||
|         """Ensure that custom QuerySetManager instances work as expected. |         """Ensure that custom QuerySetManager instances work as expected. | ||||||
|         """ |         """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user