Squashed commit of the following:
commit 48f988acd728f1193b57df8cf6b0154d69c15099 Merge: 6526923 1304f27 Author: 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). commit 6526923345efd768044c4fba770a8a3ada161a40 Author: 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 commit 24fd1acce68341361331e033d1692d61a936f871 Author: Ross Lawley <ross.lawley@gmail.com> Date: Thu Jul 26 14:14:10 2012 +0100 Version bump commit cbb9235dc5d863ee0bb8a315c976581e71b6a641 Merge: 6459d4c 19ec2c9 Author: Ross Lawley <ross.lawley@gmail.com> Date: Wed Jul 25 15:12:34 2012 +0100 Merge branch 'master' of github.com:hmarr/mongoengine commit 19ec2c9bc98db454680e681373f3fcd3b0f79a6c Merge: 3070e0b 601f0eb Author: 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 commit 6459d4c0b60229edcd4d562898833f221d00ebf4 Author: 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. commit 1304f2721f7850b223950edb85ec7c141255176c Author: Chris Faulkner <thefaulkner@gmail.com> Date: Tue Jul 24 14:06:43 2012 -0700 Proper syntax for RST notes (so they actually render). commit 598ffd3e5c107990dd41995d0bbb21bf13f67fb5 Author: Ross Lawley <ross.lawley@gmail.com> Date: Mon Jul 23 15:32:02 2012 +0100 Fixed documentation commit 601f0eb1682ebd9c9eb67f1b68b76bdd2cf3d8c7 Author: Max Countryman <maxc@me.com> Date: Fri Jul 20 19:12:43 2012 -0700 Correcting typo in DynamicField docstring
This commit is contained in:
parent
1a4533a9cf
commit
3628a7653c
@ -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 `_`
|
||||
"""
|
||||
|
@ -169,7 +169,7 @@ class IntField(BaseField):
|
||||
def prepare_query_value(self, op, value):
|
||||
if value is None:
|
||||
return value
|
||||
|
||||
|
||||
return int(value)
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ class FloatField(BaseField):
|
||||
def prepare_query_value(self, op, value):
|
||||
if value is None:
|
||||
return value
|
||||
|
||||
|
||||
return float(value)
|
||||
|
||||
|
||||
@ -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
|
||||
"""
|
||||
|
@ -806,9 +806,9 @@ class QuerySet(object):
|
||||
keyword argument called :attr:`defaults`.
|
||||
|
||||
.. note:: This requires two separate operations and therefore a
|
||||
race condition exists. Because there are no transactions in mongoDB
|
||||
other approaches should be investigated, to ensure you don't
|
||||
accidently duplicate data when using this method.
|
||||
race condition exists. Because there are no transactions in mongoDB
|
||||
other approaches should be investigated, to ensure you don't
|
||||
accidently duplicate data when using this method.
|
||||
|
||||
:param write_options: optional extra keyword arguments used if we
|
||||
have to create a new document.
|
||||
@ -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()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user