diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index a962a82b6..e157c9f34 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -81,9 +81,7 @@ def __init__(self, *args, **values): ) __auto_convert = values.pop("__auto_convert", True) - __only_fields = set(values.pop("__only_fields", values)) - _created = values.pop("_created", True) signals.pre_init.send(self.__class__, document=self, values=values) @@ -130,7 +128,6 @@ def __init__(self, *args, **values): else: FileField = _import_class("FileField") for key, value in iteritems(values): - key = self._reverse_db_field_map.get(key, key) if key in self._fields or key in ("id", "pk", "_cls"): if __auto_convert and value is not None: field = self._fields.get(key) @@ -743,7 +740,6 @@ def _from_son(cls, son, _auto_dereference=True, only_fields=None, created=False) data = {} for key, value in iteritems(son): key = str(key) - key = cls._db_field_map.get(key, key) data[key] = value # Return correct subclass for document type @@ -756,19 +752,25 @@ def _from_son(cls, son, _auto_dereference=True, only_fields=None, created=False) if not _auto_dereference: fields = copy.deepcopy(fields) + _conflict_cached_data = {} for field_name, field in iteritems(fields): field._auto_dereference = _auto_dereference if field.db_field in data: value = data[field.db_field] try: - data[field_name] = ( - value if value is None else field.to_python(value) - ) + if field_name in data: + _conflict_cached_data[field_name] = ( + value if value is None else field.to_python(value) + ) + else: + data[field_name] = ( + value if value is None else field.to_python(value) + ) if field_name != field.db_field: del data[field.db_field] except (AttributeError, ValueError) as e: errors_dict[field_name] = e - + data.update(_conflict_cached_data) if errors_dict: errors = "\n".join(["%s - %s" % (k, v) for k, v in errors_dict.items()]) msg = "Invalid data to create a `%s` instance.\n%s" % ( diff --git a/tests/document/test_instance.py b/tests/document/test_instance.py index 9b4a16e5a..381db33f0 100644 --- a/tests/document/test_instance.py +++ b/tests/document/test_instance.py @@ -297,6 +297,28 @@ def rank(self): self.assertEqual(Person.objects.get(name="Jack").rank, "Corporal") self.assertEqual(Person.objects.get(name="Fred").rank, "Private") + def test_db_field_conflict(self): + """Ensure two db field will not conflict.""" + + class Person(Document): + name = StringField(required=True) + age = IntField(required=False, db_field="gregorian_age") + lunar_age = IntField(required=False, db_field="age") + + Person.drop_collection() + p = Person(name="Jack", age="18", lunar_age="20") + + self.assertEqual(p._data, {'age': 18, 'id': None, 'name': u'Jack', 'lunar_age': 20}) + self.assertEqual(p.to_mongo(), bson.SON([('name', u'Jack'), ('gregorian_age', 18), ('age', 20)])) + + Person(name="Jack", age="18", lunar_age="20").save() + + Person(name="Fred", age="28", lunar_age="30").save() + + p = Person.objects.get(name="Jack") + self.assertEqual(p.age, 18) + self.assertEqual(Person.objects.get(name="Fred").lunar_age, 30) + def test_db_embedded_doc_field_load(self): """Ensure we load embedded document data correctly.""" @@ -351,7 +373,6 @@ class User(Document): meta = {"allow_inheritance": True} with self.assertRaises(ValueError) as e: - class EmailUser(User): email = StringField(primary_key=True) @@ -750,8 +771,8 @@ class Doc(Document): d = ( Doc(embedded_field=[Embedded(string="Hi")]) - .to_mongo(use_db_field=False) - .to_dict() + .to_mongo(use_db_field=False) + .to_dict() ) self.assertEqual(d["embedded_field"], [{"string": "Hi"}]) @@ -1615,7 +1636,7 @@ class User(self.Person): self.assertEqual(person.active, False) def test__get_changed_fields_same_ids_reference_field_does_not_enters_infinite_loop_embedded_doc( - self + self ): # Refers to Issue #1685 class EmbeddedChildModel(EmbeddedDocument): @@ -1629,7 +1650,7 @@ class ParentModel(Document): self.assertEqual(changed_fields, []) def test__get_changed_fields_same_ids_reference_field_does_not_enters_infinite_loop_different_doc( - self + self ): # Refers to Issue #1685 class User(Document): @@ -2108,7 +2129,6 @@ def test_duplicate_db_fields_raise_invalid_document_error(self): declare the same db_field. """ with self.assertRaises(InvalidDocumentError): - class Foo(Document): name = StringField() name2 = StringField(db_field="name") @@ -2394,7 +2414,6 @@ class Foo(Document): def test_invalid_reverse_delete_rule_raise_errors(self): with self.assertRaises(InvalidDocumentError): - class Blog(Document): content = StringField() authors = MapField( @@ -2405,7 +2424,6 @@ class Blog(Document): ) with self.assertRaises(InvalidDocumentError): - class Parents(EmbeddedDocument): father = ReferenceField("Person", reverse_delete_rule=DENY) mother = ReferenceField("Person", reverse_delete_rule=DENY) @@ -2643,7 +2661,6 @@ def test_override_method_with_field(self): the "validate" method. """ with self.assertRaises(InvalidDocumentError): - class Blog(Document): validate = DictField() @@ -2907,8 +2924,8 @@ def __str__(self): [ str(b) for b in Book.objects.filter( - Q(extra__a=bob) | Q(author=bob) | Q(extra__b=bob) - ) + Q(extra__a=bob) | Q(author=bob) | Q(extra__b=bob) + ) ] ), "1,2,3,4", @@ -2920,10 +2937,10 @@ def __str__(self): [ str(b) for b in Book.objects.filter( - Q(extra__a__all=[karl, susan]) - | Q(author__all=[karl, susan]) - | Q(extra__b__all=[karl.to_dbref(), susan.to_dbref()]) - ) + Q(extra__a__all=[karl, susan]) + | Q(author__all=[karl, susan]) + | Q(extra__b__all=[karl.to_dbref(), susan.to_dbref()]) + ) ] ), "1", @@ -2935,13 +2952,13 @@ def __str__(self): [ str(b) for b in Book.objects.filter( - __raw__={ - "$where": """ + __raw__={ + "$where": """ function(){ return this.name == '1' || this.name == '2';}""" - } - ) + } + ) ] ), "1,2", diff --git a/tests/fields/test_fields.py b/tests/fields/test_fields.py index d9279c22e..11623cf12 100644 --- a/tests/fields/test_fields.py +++ b/tests/fields/test_fields.py @@ -1224,7 +1224,10 @@ class A(Document): a = A(b=B(c=C(txt="hi"))) a.validate() - a = A(b={"c": {"txt": "hi"}}) + a = A(b=B(c={"txt": "hi"})) + a.validate() + + a = A(b={"fc": {"txt": "hi"}}) a.validate() def test_double_embedded_db_field_from_son(self):