Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

db_field isn't used if field is not present in document, leading to validation errors #1102

Open
lgo opened this issue Aug 21, 2015 · 2 comments

Comments

@lgo
Copy link

lgo commented Aug 21, 2015

This bug has arisen from changing the db_field of a value due to the new schema of that value having validation errors, in an attempt to migrate the data.

It seems that if the document does not have the key db_field it will fall back to the field name still, which is somewhat unexpected behaviour and can cause unexpected validation errors.

As this behaviour is not described in the documentation at all, it should at least be put in as warnings if not resolved.

The below code reproduces the bug described.

from mongoengine import *

class TestDocument(Document):
    attributeName = StringField(db_field="fieldName")

if __name__ == '__main__':

    db = connect('Issue#1102')
    db.drop_database('Issue#1102')

    # Create Test Document
    d = TestDocument()
    d.save()

    # get and validate object
    d2 = TestDocument.objects().first()
    # VALID
    d2.validate()

    # Add in bad field
    TestDocument.objects.update(__raw__={
        "$set": {
            "attributeName": 1
        }
    })

    # get and validate object
    d3 = TestDocument.objects().first()

    # FAILS
    try:
        d3.validate()
    except ValidationError as e:
        print("Failed d3.validate(). %s" % e)

    # Add in good field
    TestDocument.objects.update(__raw__={
        "$set": {
            "fieldName": "string"
        }
    })

    # get and validate object
    d4 = TestDocument.objects().first()
    # VALID
    d4.validate()
touilleMan added a commit to touilleMan/mongoengine that referenced this issue Sep 21, 2015
@touilleMan
Copy link
Member

Hi,

I've created a unittest to show your bug (see touilleMan@53faee2).

I think the code responsible for field renaming is dispatched between base.Document._from_son and in base.Document.__init__

Given _from_son create an a Document (hence using __init__), the behavior of the field renaming is changing (depending only __init__ is called or _from_son + __init__. This makes the fix of this bug a bit tricky...

@wojcikstefan
Copy link
Member

I just replicated this behavior in v0.11.0. Still a bug:

In [47]: class TestDocument(Document):
        attributeName = StringField(db_field="fieldName")
   ....:

In [48]: TestDocument.drop_collection()

In [49]: TestDocument._get_collection().insert({'attributeName': 1})  # equal to the field name, but not the db_field
Out[49]: ObjectId('586344e7c6e47b16a6b606d6')

In [50]: TestDocument._get_collection().find_one()
Out[50]: {u'_id': ObjectId('586344e7c6e47b16a6b606d6'), u'attributeName': 1}

In [51]: doc = TestDocument.objects.first()

In [52]: doc._data
Out[52]: {"id": ObjectId('586344e7c6e47b16a6b606d6'), "attributeName": 1}

In [53]: doc.attributeName  # this should be None
Out[53]: 1

@wojcikstefan wojcikstefan self-assigned this Dec 28, 2016
@wojcikstefan wojcikstefan removed their assignment Mar 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants