Squashed commit of the following:
commit48f988acd7Merge:65269231304f27Author: Ross Lawley <ross.lawley@gmail.com> Date: Thu Jul 26 08:17:45 2012 -0700 Merge pull request #44 from faulkner/fix-notes Proper syntax for RST notes (so they actually render). commit6526923345Author: Ross Lawley <ross.lawley@gmail.com> Date: Thu Jul 26 16:00:32 2012 +0100 Fixed recursion loading bug in _get_changed_fields fixes hmarr/mongoengine#548 commit24fd1acce6Author: Ross Lawley <ross.lawley@gmail.com> Date: Thu Jul 26 14:14:10 2012 +0100 Version bump commitcbb9235dc5Merge:6459d4c19ec2c9Author: Ross Lawley <ross.lawley@gmail.com> Date: Wed Jul 25 15:12:34 2012 +0100 Merge branch 'master' of github.com:hmarr/mongoengine commit19ec2c9bc9Merge:3070e0b601f0ebAuthor: Ross Lawley <ross.lawley@gmail.com> Date: Wed Jul 25 07:12:07 2012 -0700 Merge pull request #545 from maxcountryman/patch-1 Correcting typo in DynamicField docstring commit6459d4c0b6Author: Ross Lawley <ross.lawley@gmail.com> Date: Wed Jul 25 14:55:10 2012 +0100 Fixed issue with custom queryset manager expecting explict variable names If using / expecting kwargs you have to call the queryset manager explicitly. commit1304f2721fAuthor: Chris Faulkner <thefaulkner@gmail.com> Date: Tue Jul 24 14:06:43 2012 -0700 Proper syntax for RST notes (so they actually render). commit598ffd3e5cAuthor: Ross Lawley <ross.lawley@gmail.com> Date: Mon Jul 23 15:32:02 2012 +0100 Fixed documentation commit601f0eb168Author: Max Countryman <maxc@me.com> Date: Fri Jul 20 19:12:43 2012 -0700 Correcting typo in DynamicField docstring
This commit is contained in:
		| @@ -3,6 +3,14 @@ Changelog | ||||
| ========= | ||||
|  | ||||
|  | ||||
| Changes in 0.6.18 | ||||
| ================= | ||||
| - Fixed recursion loading bug in _get_changed_fields | ||||
|  | ||||
| Changes in 0.6.17 | ||||
| ================= | ||||
| - Fixed issue with custom queryset manager expecting explict variable names | ||||
|  | ||||
| Changes in 0.6.16 | ||||
| ================= | ||||
| - Fixed issue where db_alias wasn't inherited | ||||
| @@ -27,7 +35,7 @@ Changes in 0.6.14 | ||||
| - Added support for add_to_set and each | ||||
|  | ||||
| Changes in 0.6.13 | ||||
| ================ | ||||
| ================= | ||||
| - Fixed EmbeddedDocument db_field validation issue | ||||
| - Fixed StringField unicode issue | ||||
| - Fixes __repr__ modifying the cursor | ||||
|   | ||||
| @@ -259,6 +259,35 @@ as the constructor's argument:: | ||||
|         content = StringField() | ||||
|  | ||||
|  | ||||
| .. _one-to-many-with-listfields: | ||||
|  | ||||
| One to Many with ListFields | ||||
| ''''''''''''''''''''''''''' | ||||
|  | ||||
| If you are implementing a one to many relationship via a list of references, | ||||
| then the references are stored as DBRefs and to query you need to pass an | ||||
| instance of the object to the query:: | ||||
|  | ||||
|     class User(Document): | ||||
|         name = StringField() | ||||
|  | ||||
|     class Page(Document): | ||||
|         content = StringField() | ||||
|         authors = ListField(ReferenceField(User)) | ||||
|  | ||||
|     bob = User(name="Bob Jones").save() | ||||
|     john = User(name="John Smith").save() | ||||
|  | ||||
|     Page(content="Test Page", authors=[bob, john]).save() | ||||
|     Page(content="Another Page", authors=[john]).save() | ||||
|  | ||||
|     # Find all pages Bob authored | ||||
|     Page.objects(authors__in=[bob]) | ||||
|  | ||||
|     # Find all pages that both Bob and John have authored | ||||
|     Page.objects(authors__all=[bob, john]) | ||||
|  | ||||
|  | ||||
| Dealing with deletion of referred documents | ||||
| ''''''''''''''''''''''''''''''''''''''''''' | ||||
| By default, MongoDB doesn't check the integrity of your data, so deleting | ||||
|   | ||||
| @@ -12,7 +12,7 @@ from signals import * | ||||
| __all__ = (document.__all__ + fields.__all__ + connection.__all__ + | ||||
|            queryset.__all__ + signals.__all__) | ||||
|  | ||||
| VERSION = (0, 6, 16) | ||||
| VERSION = (0, 6, 18) | ||||
|  | ||||
|  | ||||
| def get_version(): | ||||
|   | ||||
| @@ -1017,9 +1017,10 @@ Invalid data to create a `%s` instance.\n%s""".strip() % (cls._class_name, error | ||||
|             field_list.update(self._dynamic_fields) | ||||
|  | ||||
|         for field_name in field_list: | ||||
|  | ||||
|             db_field_name = self._db_field_map.get(field_name, field_name) | ||||
|             key = '%s.' % db_field_name | ||||
|             field = getattr(self, field_name, None) | ||||
|             field = self._data.get(field_name, None) | ||||
|             if hasattr(field, 'id'): | ||||
|                 if field.id in inspected: | ||||
|                     continue | ||||
|   | ||||
| @@ -375,7 +375,7 @@ class DynamicDocument(Document): | ||||
|     :class:`~mongoengine.DynamicField` and data can be attributed to that | ||||
|     field. | ||||
|  | ||||
|     ..note:: | ||||
|     .. note:: | ||||
|  | ||||
|         There is one caveat on Dynamic Documents: fields cannot start with `_` | ||||
|     """ | ||||
|   | ||||
| @@ -451,7 +451,7 @@ class GenericEmbeddedDocumentField(BaseField): | ||||
|  | ||||
|     Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. | ||||
|  | ||||
|     ..note :: You can use the choices param to limit the acceptable | ||||
|     .. note:: You can use the choices param to limit the acceptable | ||||
|     EmbeddedDocument types | ||||
|     """ | ||||
|  | ||||
| @@ -483,7 +483,7 @@ class GenericEmbeddedDocumentField(BaseField): | ||||
|  | ||||
|  | ||||
| class DynamicField(BaseField): | ||||
|     """A tryly dynamic field type capable of handling different and varying | ||||
|     """A truly dynamic field type capable of handling different and varying | ||||
|     types of data. | ||||
|  | ||||
|     Used by :class:`~mongoengine.DynamicDocument` to handle dynamic data""" | ||||
| @@ -530,6 +530,8 @@ class ListField(ComplexBaseField): | ||||
|     """A list field that wraps a standard field, allowing multiple instances | ||||
|     of the field to be used as a list in the database. | ||||
|  | ||||
|     If using with ReferenceFields see: :ref:`one-to-many-with-listfields` | ||||
|  | ||||
|     .. note:: | ||||
|         Required means it cannot be empty - as the default for ListFields is [] | ||||
|     """ | ||||
| @@ -766,10 +768,10 @@ class GenericReferenceField(BaseField): | ||||
|     """A reference to *any* :class:`~mongoengine.document.Document` subclass | ||||
|     that will be automatically dereferenced on access (lazily). | ||||
|  | ||||
|     ..note ::  Any documents used as a generic reference must be registered in the | ||||
|     .. note:: Any documents used as a generic reference must be registered in the | ||||
|     document registry.  Importing the model will automatically register it. | ||||
|  | ||||
|     ..note :: You can use the choices param to limit the acceptable Document types | ||||
|     .. note:: You can use the choices param to limit the acceptable Document types | ||||
|  | ||||
|     .. versionadded:: 0.3 | ||||
|     """ | ||||
|   | ||||
| @@ -816,8 +816,8 @@ class QuerySet(object): | ||||
|  | ||||
|         :param auto_save: if the object is to be saved automatically if not found. | ||||
|  | ||||
|         .. versionchanged:: 0.6 - added `auto_save` | ||||
|         .. versionadded:: 0.3 | ||||
|         .. versionupdated:: 0.6 - added `auto_save` | ||||
|         """ | ||||
|         defaults = query.get('defaults', {}) | ||||
|         if 'defaults' in query: | ||||
| @@ -1882,9 +1882,9 @@ class QuerySetManager(object): | ||||
|         queryset = queryset_class(owner, owner._get_collection()) | ||||
|         if self.get_queryset: | ||||
|             var_names = self.get_queryset.func_code.co_varnames | ||||
|             if var_names == ('queryset',): | ||||
|             if len(var_names) == 1: | ||||
|                 queryset = self.get_queryset(queryset) | ||||
|             elif var_names == ('doc_cls', 'queryset',): | ||||
|             elif len(var_names) == 2: | ||||
|                 queryset = self.get_queryset(owner, queryset) | ||||
|             else: | ||||
|                 queryset = partial(self.get_queryset, owner, queryset) | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| %define srcname mongoengine | ||||
|  | ||||
| Name:           python-%{srcname} | ||||
| Version:        0.6.16 | ||||
| Version:        0.6.18 | ||||
| Release:        1%{?dist} | ||||
| Summary:        A Python Document-Object Mapper for working with MongoDB | ||||
|  | ||||
|   | ||||
| @@ -579,6 +579,64 @@ class QuerySetTest(unittest.TestCase): | ||||
|         Blog.objects.insert([blog2, blog3], write_options={'continue_on_error': True}) | ||||
|         self.assertEqual(Blog.objects.count(), 3) | ||||
|  | ||||
|     def test_get_changed_fields_query_count(self): | ||||
|  | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             owns = ListField(ReferenceField('Organization')) | ||||
|             projects = ListField(ReferenceField('Project')) | ||||
|  | ||||
|         class Organization(Document): | ||||
|             name = StringField() | ||||
|             owner = ReferenceField('Person') | ||||
|             employees = ListField(ReferenceField('Person')) | ||||
|  | ||||
|         class Project(Document): | ||||
|             name = StringField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|         Organization.drop_collection() | ||||
|         Project.drop_collection() | ||||
|  | ||||
|         r1 = Project(name="r1").save() | ||||
|         r2 = Project(name="r2").save() | ||||
|         r3 = Project(name="r3").save() | ||||
|         p1 = Person(name="p1", projects=[r1, r2]).save() | ||||
|         p2 = Person(name="p2", projects=[r2]).save() | ||||
|         o1 = Organization(name="o1", employees=[p1]).save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|  | ||||
|             fresh_o1 = Organization.objects.get(id=o1.id) | ||||
|             self.assertEqual(1, q) | ||||
|             fresh_o1._get_changed_fields() | ||||
|             self.assertEqual(1, q) | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|  | ||||
|             fresh_o1 = Organization.objects.get(id=o1.id) | ||||
|             fresh_o1.save() | ||||
|  | ||||
|             self.assertEquals(q, 2) | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|  | ||||
|             fresh_o1 = Organization.objects.get(id=o1.id) | ||||
|             fresh_o1.save(cascade=False) | ||||
|  | ||||
|             self.assertEquals(q, 2) | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|  | ||||
|             fresh_o1 = Organization.objects.get(id=o1.id) | ||||
|             fresh_o1.employees.append(p2) | ||||
|             fresh_o1.save(cascade=False) | ||||
|  | ||||
|             self.assertEquals(q, 3) | ||||
|  | ||||
|     def test_slave_okay(self): | ||||
|         """Ensures that a query can take slave_okay syntax | ||||
| @@ -2228,28 +2286,28 @@ class QuerySetTest(unittest.TestCase): | ||||
|             date = DateTimeField(default=datetime.now) | ||||
|  | ||||
|             @queryset_manager | ||||
|             def objects(doc_cls, queryset): | ||||
|                 return queryset(deleted=False) | ||||
|             def objects(cls, qryset): | ||||
|                 return qryset(deleted=False) | ||||
|  | ||||
|             @queryset_manager | ||||
|             def music_posts(doc_cls, queryset): | ||||
|                 return queryset(tags='music', deleted=False).order_by('-date') | ||||
|             def music_posts(doc_cls, queryset, deleted=False): | ||||
|                 return queryset(tags='music', | ||||
|                                 deleted=deleted).order_by('date') | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
|         post1 = BlogPost(tags=['music', 'film']) | ||||
|         post1.save() | ||||
|         post2 = BlogPost(tags=['music']) | ||||
|         post2.save() | ||||
|         post3 = BlogPost(tags=['film', 'actors']) | ||||
|         post3.save() | ||||
|         post4 = BlogPost(tags=['film', 'actors'], deleted=True) | ||||
|         post4.save() | ||||
|         post1 = BlogPost(tags=['music', 'film']).save() | ||||
|         post2 = BlogPost(tags=['music']).save() | ||||
|         post3 = BlogPost(tags=['film', 'actors']).save() | ||||
|         post4 = BlogPost(tags=['film', 'actors', 'music'], deleted=True).save() | ||||
|  | ||||
|         self.assertEqual([p.id for p in BlogPost.objects], | ||||
|         self.assertEqual([p.id for p in BlogPost.objects()], | ||||
|                          [post1.id, post2.id, post3.id]) | ||||
|         self.assertEqual([p.id for p in BlogPost.music_posts], | ||||
|                          [post2.id, post1.id]) | ||||
|         self.assertEqual([p.id for p in BlogPost.music_posts()], | ||||
|                          [post1.id, post2.id]) | ||||
|  | ||||
|         self.assertEqual([p.id for p in BlogPost.music_posts(True)], | ||||
|                          [post4.id]) | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user