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

mongoengine.errors.ValidationError: A ReferenceField only accepts DBRef or documents #997

Closed
dmitry-saritasa opened this issue May 11, 2015 · 5 comments · Fixed by #1921
Closed

Comments

@dmitry-saritasa
Copy link

python 2.7.8, latest mongoengine.zip from master:
mongoengine/fields.py, line 990

def validate(self, value):
        if not isinstance(value, (self.document_type, DBRef)):
            self.error("A ReferenceField only accepts DBRef or documents")

        if isinstance(value, Document) and value.id is None:
            self.error('You can only reference documents once they have been '
                       'saved to the database')

first "if" gives the following code

    s = Shift.objects.get(id='554ad0c18a5da50025b7c7c3')
    print s.guard.fname
    #guard = Guard.objects.get(id='55355d7083ba88e23f8b4569')
    guard = Guard.objects.get(id='54d4361183ba88c24a8b4567')
    print guard.fullname
    s.guard = guard
    s.save()

mongoengine.errors.ValidationError: A ReferenceField only accepts DBRef or documents

traceback:
https://gist.github.com/saritasa/27d82f33e3cc33afe1cb

If I run it again - everything works. If I uncomment the first guard and comment 2nd guard, I get this error again. Run 4th time - and error gone.

value is ObjectId type, when I debug code.

Sample data:

{
    "_id" : ObjectId("554ad0c18a5da50025b7c7c3"),
    "parent" : ObjectId("55241c448a5da5002616ede5"),
    "type" : "reassignment",
    "date" : ISODate("2015-05-15T00:00:00.000Z"),
    "school" : ObjectId("55241a8983ba889a678b4567"),
    "location" : ObjectId("55241ae583ba88d46c8b4567"),
    "guard" : ObjectId("54d4361183ba88c24a8b4567"),
    "name" : "1st shift",
    "weekday" : 5,
    "start" : "08:00:00",
    "finish" : "08:30:00",
    "start_sec" : 28800,
    "finish_sec" : 30600,
    "weight" : 28800,
    "holidays" : [],
    "created_at" : ISODate("2015-05-07T02:41:05.618Z"),
    "updated_at" : ISODate("2015-05-11T10:01:58.139Z"),
    "guard_name" : "Guard2Vadik alt Kuz",
    "school_name" : "VictorHigh",
    "location_name" : "Joslin / Gard",
    "guard_phone" : "1231231234",
    "parent_cache" : {
        "_id" : ObjectId("55241c448a5da5002616ede5"),
        "finish" : "08:30:00",
        "weight" : 28800,
        "start_sec" : 28800,
        "finish_sec" : 30600,
        "start" : "08:00:00",
        "guard" : ObjectId("552411f883ba8842658b4567"),
        "type" : "regular"
    }
}

Full shift class is here:
https://gist.github.com/saritasa/ad9387a1259141db4a04

any ideas?

@MRigal
Copy link
Member

MRigal commented Jun 2, 2015

Not really, but this doesn't sound good... There is quite a bit to do here, but if I have time, I may inspect that further. Else, feel free to submit a PR, at least with a proper (failing) test, even better with the fix :-)

@MRigal MRigal modified the milestone: 0.10.1 Jun 23, 2015
@arnaudriegert
Copy link

I had a similar problem and apparently it occurs when the ReferenceField's document class is abstract.

In my case, inside the ReferenceField.validate method, type(value) was myapp.mymodule.documents.subclassmodule.FooBar while self.document_type was myapp.mymodule.documents..Bar (there were actually two dots between documents and Bar).

FooBar is a subclass of Bar (more precisely, it was declared as FooBar(FooBarSerializer, Bar):), but isinstance(value, self.document_type) evaluated to False (so did issubclass(type(value), self.document_type) although I believe that's exactly equivalent).

Hope this helps.

@rahulrameshan
Copy link

try using
s.guard = guard..to_dbref()
s.save()

@0xWilliamWang
Copy link

@rahulrameshan you are right, thank you.

@letoss
Copy link

letoss commented Apr 11, 2022

Mongoengine version: 0.23.1
Hello, I arrived at this issue after dealing with the same. I actually realized that there are two ways on solving it.

This one returns an ObjectId

guard = Guard.objects.get(id='54d4361183ba88c24a8b4567')
s.guard = guard.id
s.save()

In case you already have the guard ID, you don't need to retrieve the instance from the DB, you could just do:

from bson.objectid import ObjectId
g.guard = ObjectId('54d4361183ba88c24a8b4567')
s.save()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants