diff --git a/mongoengine/base/datastructures.py b/mongoengine/base/datastructures.py index d1b5ae76..dcc1f092 100644 --- a/mongoengine/base/datastructures.py +++ b/mongoengine/base/datastructures.py @@ -120,6 +120,9 @@ class BaseList(list): super(BaseList, self).__init__(list_items) def __getitem__(self, key): + # change index to positive value because MongoDB does not support negative one + if isinstance(key, int) and key < 0: + key = len(self) + key value = super(BaseList, self).__getitem__(key) if isinstance(key, slice): diff --git a/tests/document/test_instance.py b/tests/document/test_instance.py index 609d0690..a5c21323 100644 --- a/tests/document/test_instance.py +++ b/tests/document/test_instance.py @@ -41,7 +41,7 @@ from tests.utils import MongoDBTestCase, get_as_pymongo TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__), "../fields/mongoengine.png") -class TestInstance(MongoDBTestCase): +class TestDocumentInstance(MongoDBTestCase): def setUp(self): class Job(EmbeddedDocument): name = StringField() @@ -3617,6 +3617,51 @@ class TestInstance(MongoDBTestCase): assert b._instance == a assert idx == 2 + def test_updating_listfield_manipulate_list(self): + class Company(Document): + name = StringField() + employees = ListField(field=DictField()) + + Company.drop_collection() + + comp = Company(name="BigBank", employees=[{"name": "John"}]) + comp.save() + comp.employees.append({"name": "Bill"}) + comp.save() + + stored_comp = get_as_pymongo(comp) + self.assertEqual( + stored_comp, + { + "_id": comp.id, + "employees": [{"name": "John"}, {"name": "Bill"}], + "name": "BigBank", + }, + ) + + comp = comp.reload() + comp.employees[0]["color"] = "red" + comp.employees[-1]["color"] = "blue" + comp.employees[-1].update({"size": "xl"}) + comp.save() + + assert len(comp.employees) == 2 + assert comp.employees[0] == {"name": "John", "color": "red"} + assert comp.employees[1] == {"name": "Bill", "size": "xl", "color": "blue"} + + stored_comp = get_as_pymongo(comp) + self.assertEqual( + stored_comp, + { + "_id": comp.id, + "employees": [ + {"name": "John", "color": "red"}, + {"size": "xl", "color": "blue", "name": "Bill"}, + ], + "name": "BigBank", + }, + ) + def test_falsey_pk(self): """Ensure that we can create and update a document with Falsey PK."""