Repository: MongoEngine/mongoengine

Issue:
Error in documentation?
Maybe an error in Documentation: in section "2.3.2. Dynamic document schemas" you've writing that:

> There is one caveat on Dynamic Documents: fields cannot start with _

But I tested some filed that start with _ and still working done, also if are declared or not declared.

http://docs.mongoengine.org/guide/defining-documents.html?highlight=DynamicDocument


Discussion:
HI @domenicomonaco, thanks for reporting this. I agree that the documentation is not accurate but there is a limitation for undeclared fields. In fact it seems that fields that aren't declared can't start by underscores. Fields that are declared can start by underscores. see below:
```
    def test_fields_containing_underscore(self):
        """Ensure we can query dynamic fields"""
        class WeirdPerson(DynamicDocument):
            name = StringField()
            _name = StringField()

        WeirdPerson.drop_collection()

        p = WeirdPerson(name='Dean', _name='Dean')
        p.save()

        raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id)
        self.assertEqual(
            raw_p,
            {
                '_id': p.id,
                '_name': u'Dean',
                'name': u'Dean'
            }
        )

        p.name = 'OldDean'
        p._name = 'NewDean'
        p._newattr1 = 'garbage'    # Unknown fields won't be added
        p.save()
        raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id)
        self.assertEqual(
            raw_p,
            {
                '_id': p.id,
                '_name': u'NewDean',
                'name': u'OldDean',
            }
        )
```

I'll update the documentation to reflect this more accurately

Resolving patch:
diff --git a/mongoengine/document.py b/mongoengine/document.py
--- a/mongoengine/document.py
+++ b/mongoengine/document.py
@@ -1016,7 +1016,7 @@ class DynamicDocument(six.with_metaclass(TopLevelDocumentMetaclass, Document)):
 
     .. note::
 
-        There is one caveat on Dynamic Documents: fields cannot start with `_`
+        There is one caveat on Dynamic Documents: undeclared fields cannot start with `_`
     """
 
     # The __metaclass__ attribute is removed by 2to3 when running with Python3


Test patch:
diff --git a/tests/document/dynamic.py b/tests/document/dynamic.py
--- a/tests/document/dynamic.py
+++ b/tests/document/dynamic.py
@@ -1,16 +1,15 @@
 import unittest
 
 from mongoengine import *
-from mongoengine.connection import get_db
+from tests.utils import MongoDBTestCase
 
-__all__ = ("DynamicTest", )
+__all__ = ("TestDynamicDocument", )
 
 
-class DynamicTest(unittest.TestCase):
+class TestDynamicDocument(MongoDBTestCase):
 
     def setUp(self):
-        connect(db='mongoenginetest')
-        self.db = get_db()
+        super(TestDynamicDocument, self).setUp()
 
         class Person(DynamicDocument):
             name = StringField()
@@ -98,6 +97,72 @@ def test_reload_dynamic_field(self):
         self.assertEqual(len(p._data), 4)
         self.assertEqual(sorted(p._data.keys()), ['_cls', 'age', 'id', 'name'])
 
+    def test_fields_without_underscore(self):
+        """Ensure we can query dynamic fields"""
+        Person = self.Person
+
+        p = self.Person(name='Dean')
+        p.save()
+
+        raw_p = Person.objects.as_pymongo().get(id=p.id)
+        self.assertEqual(
+            raw_p,
+            {
+                '_cls': u'Person',
+                '_id': p.id,
+                'name': u'Dean'
+             }
+        )
+
+        p.name = 'OldDean'
+        p.newattr = 'garbage'
+        p.save()
+        raw_p = Person.objects.as_pymongo().get(id=p.id)
+        self.assertEqual(
+            raw_p,
+            {
+                '_cls': u'Person',
+                '_id': p.id,
+                'name': 'OldDean',
+                'newattr': u'garbage'
+            }
+        )
+
+    def test_fields_containing_underscore(self):
+        """Ensure we can query dynamic fields"""
+        class WeirdPerson(DynamicDocument):
+            name = StringField()
+            _name = StringField()
+
+        WeirdPerson.drop_collection()
+
+        p = WeirdPerson(name='Dean', _name='Dean')
+        p.save()
+
+        raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id)
+        self.assertEqual(
+            raw_p,
+            {
+                '_id': p.id,
+                '_name': u'Dean',
+                'name': u'Dean'
+            }
+        )
+
+        p.name = 'OldDean'
+        p._name = 'NewDean'
+        p._newattr1 = 'garbage'    # Unknown fields won't be added
+        p.save()
+        raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id)
+        self.assertEqual(
+            raw_p,
+            {
+                '_id': p.id,
+                '_name': u'NewDean',
+                'name': u'OldDean',
+            }
+        )
+
     def test_dynamic_document_queries(self):
         """Ensure we can query dynamic fields"""
         p = self.Person()
@@ -369,5 +434,6 @@ class Person(DynamicDocument):
         person.save()
         self.assertEqual(Person.objects.first().age, 35)
 
+
 if __name__ == '__main__':
     unittest.main()