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 | ||||
|  * Thomas Steinacher | ||||
|  * Tommi Komulainen | ||||
|  * Peter Landry | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| MongoEngine | ||||
| =========== | ||||
| :Info: MongoEngine is an ORM-like layer on top of PyMongo. | ||||
| :Repository: https://github.com/MongoEngine/mongoengine | ||||
| :Author: Harry Marr (http://github.com/hmarr) | ||||
| :Maintainer: Ross Lawley (http://github.com/rozza) | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,14 @@ | ||||
| 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) | ||||
| - 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='test2', published=True).save() | ||||
|     assert len(BlogPost.objects) == 2 | ||||
|     assert len(BlogPost.live_posts) == 1 | ||||
|     assert len(BlogPost.live_posts()) == 1 | ||||
|  | ||||
| Custom QuerySets | ||||
| ================ | ||||
| @@ -243,11 +243,16 @@ a document, set ``queryset_class`` to the custom class in a | ||||
| :class:`~mongoengine.Document`\ s ``meta`` dictionary:: | ||||
|  | ||||
|     class AwesomerQuerySet(QuerySet): | ||||
|         pass | ||||
|  | ||||
|         def get_awesome(self): | ||||
|             return self.filter(awesome=True) | ||||
|  | ||||
|     class Page(Document): | ||||
|         meta = {'queryset_class': AwesomerQuerySet} | ||||
|  | ||||
|     # To call: | ||||
|     Page.objects.get_awesome() | ||||
|  | ||||
| .. versionadded:: 0.4 | ||||
|  | ||||
| Aggregation | ||||
|   | ||||
| @@ -12,7 +12,7 @@ from signals import * | ||||
| __all__ = (document.__all__ + fields.__all__ + connection.__all__ + | ||||
|            queryset.__all__ + signals.__all__) | ||||
|  | ||||
| VERSION = (0, 6, 18) | ||||
| VERSION = (0, 6, 20) | ||||
|  | ||||
|  | ||||
| def get_version(): | ||||
|   | ||||
| @@ -34,7 +34,9 @@ class DeReference(object): | ||||
|  | ||||
|         doc_type = None | ||||
|         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): | ||||
|                 doc_type = doc_type.document_type | ||||
|   | ||||
| @@ -1327,7 +1327,7 @@ class UUIDField(BaseField): | ||||
|         super(UUIDField, self).__init__(**kwargs) | ||||
|  | ||||
|     def to_python(self, value): | ||||
|         if not self.binary: | ||||
|         if not self._binary: | ||||
|             if not isinstance(value, basestring): | ||||
|                 value = unicode(value) | ||||
|             return uuid.UUID(value) | ||||
|   | ||||
| @@ -765,8 +765,22 @@ class QuerySet(object): | ||||
|             key = '.'.join(parts) | ||||
|             if op is None or key not in mongo_query: | ||||
|                 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) | ||||
|                 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 | ||||
|  | ||||
| @@ -1152,8 +1166,10 @@ class QuerySet(object): | ||||
|  | ||||
|         .. versionadded:: 0.4 | ||||
|         .. 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): | ||||
|         """Load only a subset of this document's fields. :: | ||||
| @@ -1866,6 +1882,17 @@ class QuerySet(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 | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| %define srcname mongoengine | ||||
|  | ||||
| Name:           python-%{srcname} | ||||
| Version:        0.6.18 | ||||
| Version:        0.6.20 | ||||
| Release:        1%{?dist} | ||||
| Summary:        A Python Document-Object Mapper for working with MongoDB | ||||
|  | ||||
|   | ||||
| @@ -283,6 +283,7 @@ class FieldTest(unittest.TestCase): | ||||
|         uu = uuid.uuid4() | ||||
|         Person(api_key=uu).save() | ||||
|         self.assertEqual(1, Person.objects(api_key=uu).count()) | ||||
|         self.assertEqual(uu, Person.objects.first().api_key) | ||||
|  | ||||
|         person = Person() | ||||
|         valid = (uuid.uuid4(), uuid.uuid1()) | ||||
| @@ -307,6 +308,7 @@ class FieldTest(unittest.TestCase): | ||||
|         uu = uuid.uuid4() | ||||
|         Person(api_key=uu).save() | ||||
|         self.assertEqual(1, Person.objects(api_key=uu).count()) | ||||
|         self.assertEqual(uu, Person.objects.first().api_key) | ||||
|  | ||||
|         person = Person() | ||||
|         valid = (uuid.uuid4(), uuid.uuid1()) | ||||
|   | ||||
| @@ -827,7 +827,11 @@ class QuerySetTest(unittest.TestCase): | ||||
|     def test_filter_chaining(self): | ||||
|         """Ensure filters can be chained together. | ||||
|         """ | ||||
|         class Blog(Document): | ||||
|             id = StringField(unique=True, primary_key=True) | ||||
|  | ||||
|         class BlogPost(Document): | ||||
|             blog = ReferenceField(Blog) | ||||
|             title = StringField() | ||||
|             is_published = BooleanField() | ||||
|             published_date = DateTimeField() | ||||
| @@ -836,13 +840,24 @@ class QuerySetTest(unittest.TestCase): | ||||
|             def published(doc_cls, queryset): | ||||
|                 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, | ||||
|                                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, | ||||
|                                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, | ||||
|                                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)) | ||||
|         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() | ||||
|         Blog.drop_collection() | ||||
|  | ||||
|     def test_ordering(self): | ||||
|         """Ensure default ordering is applied and can be overridden. | ||||
| @@ -2277,6 +2299,28 @@ class QuerySetTest(unittest.TestCase): | ||||
|  | ||||
|         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): | ||||
|         """Ensure that custom QuerySetManager instances work as expected. | ||||
|         """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user