Allow updates with match operators (MongoEngine/mongoengine#144)
This commit is contained in:
parent
e6d796832e
commit
e2d826c412
@ -4,7 +4,8 @@ Changelog
|
||||
|
||||
Changes in 0.7.X
|
||||
================
|
||||
- Updated URLField - can have a custom validator (MongoEngine/mongoengine#136)
|
||||
- Allow updates with match operators (MongoEngine/mongoengine#144)
|
||||
- Updated URLField - now can have a override the regex (MongoEngine/mongoengine#136)
|
||||
- Allow Django AuthenticationBackends to work with Django user (hmarr/mongoengine#573)
|
||||
- Fixed reload issue with ReferenceField where dbref=False (MongoEngine/mongoengine#138)
|
||||
|
||||
|
@ -1395,6 +1395,8 @@ class QuerySet(object):
|
||||
"""
|
||||
operators = ['set', 'unset', 'inc', 'dec', 'pop', 'push', 'push_all',
|
||||
'pull', 'pull_all', 'add_to_set']
|
||||
match_operators = ['ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod',
|
||||
'all', 'size', 'exists', 'not']
|
||||
|
||||
mongo_update = {}
|
||||
for key, value in update.items():
|
||||
@ -1418,6 +1420,10 @@ class QuerySet(object):
|
||||
elif op == 'add_to_set':
|
||||
op = op.replace('_to_set', 'ToSet')
|
||||
|
||||
match = None
|
||||
if parts[-1] in match_operators:
|
||||
match = parts.pop()
|
||||
|
||||
if _doc_cls:
|
||||
# Switch field names to proper names [set in Field(name='foo')]
|
||||
fields = QuerySet._lookup_field(_doc_cls, parts)
|
||||
@ -1451,16 +1457,22 @@ class QuerySet(object):
|
||||
elif field.required or value is not None:
|
||||
value = field.prepare_query_value(op, value)
|
||||
|
||||
if match:
|
||||
match = '$' + match
|
||||
value = {match: value}
|
||||
|
||||
key = '.'.join(parts)
|
||||
|
||||
if not op:
|
||||
raise InvalidQueryError("Updates must supply an operation eg: set__FIELD=value")
|
||||
raise InvalidQueryError("Updates must supply an operation "
|
||||
"eg: set__FIELD=value")
|
||||
|
||||
if 'pull' in op and '.' in key:
|
||||
# Dot operators don't work on pull operations
|
||||
# it uses nested dict syntax
|
||||
if op == 'pullAll':
|
||||
raise InvalidQueryError("pullAll operations only support a single field depth")
|
||||
raise InvalidQueryError("pullAll operations only support "
|
||||
"a single field depth")
|
||||
|
||||
parts.reverse()
|
||||
for key in parts:
|
||||
|
@ -414,6 +414,30 @@ class QuerySetTest(unittest.TestCase):
|
||||
self.assertEqual(post.comments[0].by, 'joe')
|
||||
self.assertEqual(post.comments[0].votes.score, 4)
|
||||
|
||||
def test_updates_can_have_match_operators(self):
|
||||
|
||||
class Post(Document):
|
||||
title = StringField(required=True)
|
||||
tags = ListField(StringField())
|
||||
comments = ListField(EmbeddedDocumentField("Comment"))
|
||||
|
||||
class Comment(EmbeddedDocument):
|
||||
content = StringField()
|
||||
name = StringField(max_length=120)
|
||||
vote = IntField()
|
||||
|
||||
Post.drop_collection()
|
||||
|
||||
comm1 = Comment(content="very funny indeed", name="John S", vote=1)
|
||||
comm2 = Comment(content="kind of funny", name="Mark P", vote=0)
|
||||
|
||||
Post(title='Fun with MongoEngine', tags=['mongodb', 'mongoengine'],
|
||||
comments=[comm1, comm2]).save()
|
||||
|
||||
Post.objects().update_one(pull__comments__vote__lt=1)
|
||||
|
||||
self.assertEqual(1, len(Post.objects.first().comments))
|
||||
|
||||
def test_mapfield_update(self):
|
||||
"""Ensure that the MapField can be updated."""
|
||||
class Member(EmbeddedDocument):
|
||||
|
Loading…
x
Reference in New Issue
Block a user