Merge pull request #982 from elephanter/operator_name_in_field_name
Added __ support to escape field name in fields lookup keywords that match operators names
This commit is contained in:
commit
d6b2d8dcb5
@ -16,6 +16,7 @@ Changes in 0.9.X - DEV
|
||||
- Django support was removed and will be available as a separate extension. #958
|
||||
- Don't send a "cls" option to ensureIndex (related to https://jira.mongodb.org/browse/SERVER-769)
|
||||
- Fix for updating sorting in SortedListField. #978
|
||||
- Added __ support to escape field name in fields lookup keywords that match operators names #949
|
||||
|
||||
Changes in 0.9.0
|
||||
================
|
||||
|
@ -39,6 +39,14 @@ syntax::
|
||||
# been written by a user whose 'country' field is set to 'uk'
|
||||
uk_pages = Page.objects(author__country='uk')
|
||||
|
||||
.. note::
|
||||
|
||||
(version **0.9.1+**) if your field name is like mongodb operator name (for example
|
||||
type, lte, lt...) and you want to place it at the end of lookup keyword
|
||||
mongoengine automatically prepend $ to it. To avoid this use __ at the end of
|
||||
your lookup keyword. For example if your field name is ``type`` and you want to
|
||||
query by this field you must use ``.objects(user__type__="admin")`` instead of
|
||||
``.objects(user__type="admin")``
|
||||
|
||||
Query operators
|
||||
===============
|
||||
@ -663,4 +671,3 @@ following example shows how the substitutions are made::
|
||||
return comments;
|
||||
}
|
||||
""")
|
||||
|
||||
|
@ -44,6 +44,10 @@ def query(_doc_cls=None, _field_operation=False, **query):
|
||||
if len(parts) > 1 and parts[-1] in MATCH_OPERATORS:
|
||||
op = parts.pop()
|
||||
|
||||
#if user escape field name by __
|
||||
if len(parts) > 1 and parts[-1] == "":
|
||||
parts.pop()
|
||||
|
||||
negate = False
|
||||
if len(parts) > 1 and parts[-1] == 'not':
|
||||
parts.pop()
|
||||
|
@ -1328,7 +1328,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
self.assertEqual(1, BlogPost.objects.count())
|
||||
|
||||
def test_reverse_delete_rule_cascade_on_abstract_document(self):
|
||||
"""Ensure cascading deletion of referring documents from the database
|
||||
"""Ensure cascading deletion of referring documents from the database
|
||||
does not fail on abstract document.
|
||||
"""
|
||||
class AbstractBlogPost(Document):
|
||||
@ -1350,7 +1350,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(3, BlogPost.objects.count())
|
||||
self.Person.objects(name='Test User').delete()
|
||||
self.assertEqual(1, BlogPost.objects.count())
|
||||
self.assertEqual(1, BlogPost.objects.count())
|
||||
|
||||
def test_reverse_delete_rule_cascade_self_referencing(self):
|
||||
"""Ensure self-referencing CASCADE deletes do not result in infinite
|
||||
@ -1411,8 +1411,8 @@ class QuerySetTest(unittest.TestCase):
|
||||
self.assertEqual(1, BlogPost.objects.count())
|
||||
self.assertEqual(None, BlogPost.objects.first().category)
|
||||
|
||||
def test_reverse_delete_rule_nullify_on_abstract_document(self):
|
||||
"""Ensure nullification of references to deleted documents when
|
||||
def test_reverse_delete_rule_nullify_on_abstract_document(self):
|
||||
"""Ensure nullification of references to deleted documents when
|
||||
reference is on an abstract document.
|
||||
"""
|
||||
class AbstractBlogPost(Document):
|
||||
@ -1474,7 +1474,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(1, BlogPost.objects.count())
|
||||
self.assertRaises(OperationError, self.Person.objects.delete)
|
||||
|
||||
|
||||
def test_reverse_delete_rule_pull(self):
|
||||
"""Ensure pulling of references to deleted documents.
|
||||
"""
|
||||
@ -1511,9 +1511,9 @@ class QuerySetTest(unittest.TestCase):
|
||||
"""
|
||||
class AbstractBlogPost(Document):
|
||||
meta = {'abstract': True}
|
||||
authors = ListField(ReferenceField(self.Person,
|
||||
authors = ListField(ReferenceField(self.Person,
|
||||
reverse_delete_rule=PULL))
|
||||
|
||||
|
||||
class BlogPost(AbstractBlogPost):
|
||||
content = StringField()
|
||||
|
||||
@ -1538,7 +1538,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(post.authors, [me])
|
||||
self.assertEqual(another.authors, [])
|
||||
|
||||
|
||||
def test_delete_with_limits(self):
|
||||
|
||||
class Log(Document):
|
||||
@ -3009,7 +3009,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
def test_distinct_ListField_EmbeddedDocumentField_EmbeddedDocumentField(self):
|
||||
class Continent(EmbeddedDocument):
|
||||
continent_name = StringField()
|
||||
|
||||
|
||||
class Country(EmbeddedDocument):
|
||||
country_name = StringField()
|
||||
continent = EmbeddedDocumentField(Continent)
|
||||
@ -3026,7 +3026,7 @@ class QuerySetTest(unittest.TestCase):
|
||||
|
||||
europe = Continent(continent_name='europe')
|
||||
asia = Continent(continent_name='asia')
|
||||
|
||||
|
||||
scotland = Country(country_name="Scotland", continent=europe)
|
||||
tibet = Country(country_name="Tibet", continent=asia)
|
||||
|
||||
@ -3041,9 +3041,9 @@ class QuerySetTest(unittest.TestCase):
|
||||
country_list = Book.objects.distinct("authors.country")
|
||||
|
||||
self.assertEqual(country_list, [scotland, tibet])
|
||||
|
||||
|
||||
continent_list = Book.objects.distinct("authors.country.continent")
|
||||
|
||||
|
||||
self.assertEqual(continent_list, [europe, asia])
|
||||
|
||||
def test_distinct_ListField_ReferenceField(self):
|
||||
|
@ -208,6 +208,22 @@ class TransformTest(unittest.TestCase):
|
||||
self.assertEqual(Doc.objects(df__type=2).count(), 1) # str
|
||||
self.assertEqual(Doc.objects(df__type=16).count(), 1) # int
|
||||
|
||||
def test_last_field_name_like_operator(self):
|
||||
class EmbeddedItem(EmbeddedDocument):
|
||||
type = StringField()
|
||||
name = StringField()
|
||||
|
||||
class Doc(Document):
|
||||
item = EmbeddedDocumentField(EmbeddedItem)
|
||||
|
||||
Doc.drop_collection()
|
||||
|
||||
doc = Doc(item=EmbeddedItem(type="axe", name="Heroic axe"))
|
||||
doc.save()
|
||||
|
||||
self.assertEqual(1, Doc.objects(item__type__="axe").count())
|
||||
self.assertEqual(1, Doc.objects(item__name__="Heroic axe").count())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user