Merge remote branch 'hmarr/master'

This commit is contained in:
Florian Schlachter 2010-02-03 02:26:26 +01:00
commit df5b1f3806
5 changed files with 81 additions and 1 deletions

View File

@ -46,6 +46,8 @@ Fields
.. autoclass:: mongoengine.EmbeddedDocumentField .. autoclass:: mongoengine.EmbeddedDocumentField
.. autoclass:: mongoengine.DictField
.. autoclass:: mongoengine.ListField .. autoclass:: mongoengine.ListField
.. autoclass:: mongoengine.ObjectIdField .. autoclass:: mongoengine.ObjectIdField

View File

@ -39,6 +39,7 @@ are as follows:
* :class:`~mongoengine.FloatField` * :class:`~mongoengine.FloatField`
* :class:`~mongoengine.DateTimeField` * :class:`~mongoengine.DateTimeField`
* :class:`~mongoengine.ListField` * :class:`~mongoengine.ListField`
* :class:`~mongoengine.DictField`
* :class:`~mongoengine.ObjectIdField` * :class:`~mongoengine.ObjectIdField`
* :class:`~mongoengine.EmbeddedDocumentField` * :class:`~mongoengine.EmbeddedDocumentField`
* :class:`~mongoengine.ReferenceField` * :class:`~mongoengine.ReferenceField`
@ -75,6 +76,23 @@ document class as the first argument::
comment2 = Comment('Nice article!') comment2 = Comment('Nice article!')
page = Page(comments=[comment1, comment2]) page = Page(comments=[comment1, comment2])
Dictionary Fields
-----------------
Often, an embedded document may be used instead of a dictionary -- generally
this is recommended as dictionaries don't support validation or custom field
types. However, sometimes you will not know the structure of what you want to
store; in this situation a :class:`~mongoengine.DictField` is appropriate::
class SurveyResponse(Document):
date = DateTimeField()
user = ReferenceField(User)
answers = DictField()
survey_response = SurveyResponse(date=datetime.now(), user=request.user)
response_form = ResponseForm(request.POST)
survey_response.answers = response_form.cleaned_data()
survey_response.save()
Reference fields Reference fields
---------------- ----------------
References may be stored to other documents in the database using the References may be stored to other documents in the database using the

View File

@ -8,7 +8,7 @@ import datetime
__all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField', __all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField',
'DateTimeField', 'EmbeddedDocumentField', 'ListField', 'DateTimeField', 'EmbeddedDocumentField', 'ListField', 'DictField',
'ObjectIdField', 'ReferenceField', 'ValidationError'] 'ObjectIdField', 'ReferenceField', 'ValidationError']
@ -180,6 +180,28 @@ class ListField(BaseField):
return self.field.lookup_member(member_name) return self.field.lookup_member(member_name)
class DictField(BaseField):
"""A dictionary field that wraps a standard Python dictionary. This is
similar to an embedded document, but the structure is not defined.
.. versionadded:: 0.2.3
"""
def validate(self, value):
"""Make sure that a list of valid fields is being used.
"""
if not isinstance(value, dict):
raise ValidationError('Only dictionaries may be used in a '
'DictField')
if any(('.' in k or '$' in k) for k in value):
raise ValidationError('Invalid dictionary key name - keys may not '
'contain "." or "$" characters')
def lookup_member(self, member_name):
return BaseField(name=member_name)
class ReferenceField(BaseField): class ReferenceField(BaseField):
"""A reference to a document that will be automatically dereferenced on """A reference to a document that will be automatically dereferenced on
access (lazily). access (lazily).

View File

@ -176,6 +176,28 @@ class FieldTest(unittest.TestCase):
post.comments = 'yay' post.comments = 'yay'
self.assertRaises(ValidationError, post.validate) self.assertRaises(ValidationError, post.validate)
def test_dict_validation(self):
"""Ensure that dict types work as expected.
"""
class BlogPost(Document):
info = DictField()
post = BlogPost()
post.info = 'my post'
self.assertRaises(ValidationError, post.validate)
post.info = ['test', 'test']
self.assertRaises(ValidationError, post.validate)
post.info = {'$title': 'test'}
self.assertRaises(ValidationError, post.validate)
post.info = {'the.title': 'test'}
self.assertRaises(ValidationError, post.validate)
post.info = {'title': 'test'}
post.validate()
def test_embedded_document_validation(self): def test_embedded_document_validation(self):
"""Ensure that invalid embedded documents cannot be assigned to """Ensure that invalid embedded documents cannot be assigned to
embedded document fields. embedded document fields.

View File

@ -277,6 +277,22 @@ class QuerySetTest(unittest.TestCase):
BlogPost.drop_collection() BlogPost.drop_collection()
def test_find_dict_item(self):
"""Ensure that DictField items may be found.
"""
class BlogPost(Document):
info = DictField()
BlogPost.drop_collection()
post = BlogPost(info={'title': 'test'})
post.save()
post_obj = BlogPost.objects(info__title='test').first()
self.assertEqual(post_obj.id, post.id)
BlogPost.drop_collection()
def test_q(self): def test_q(self):
class BlogPost(Document): class BlogPost(Document):
publish_date = DateTimeField() publish_date = DateTimeField()