wlanslovenija / django-tastypie-mongoengine

MongoEngine support for django-tastypie.
Other
73 stars 59 forks source link

Creating resources containing an embedded document with a ReferencedListField doesn't work properly #58

Open bendemboski opened 11 years ago

bendemboski commented 11 years ago

This is closely related to #57. Using the same documents and resources described in that ticket, POSTing a TopLevelResource or TopLevelListResource with nonempty lists of references to ReferredResources succeeds, but the references are not actually created -- embedded.refs ends up empty.

I haven't figured out a fix for this issue, but I have a rough idea of why it's happening. It comes down to how tastypie handles m2m resources. They are not hydrated during the full_hydrate() pass, but there is a separate call to hydrate_m2m() and save_m2m() in Resource.save(). ReferencedListFields are m2m, so they follow this pattern.

The problem comes when the ReferencedListField is a member of an embedded document, because there is no logic built into the save() method to save m2m fields on embedded documents. The closest analog that tastypie supports would be a ToOneField pointing to a resource with a ToManyField. This works in tastypie because Resource.save() calls Resource.save_related(), which calls save() on the related resource that the ToOneField points to, and save() in turn calls hydrate_m2m() and save_m2m(). However, this doesn't work in our case because embedded documents aren't their own resource -- we don't call save() on them, so there is no opportunity to call hydrate_m2m() and save_m2m().

That's the nub of the problem -- the embedded documents are kind of acting like related resources, but we don't call save on them, so we don't save their m2m fields. My best idea for a fix for this is to add an is_embedded attribute to EmbeddedDocumentField and EmbeddedListField (analogous to the is_m2m attribute). Then, in MongoEngineResource.save(), notice any is_embedded fields and call their hydrate_m2m() and save_m2m() methods. Except this won't exactly work, because I think hydrate_m2m and/or save_m2m have some code that assumes they are being called in the context of a top-level resource whose object has a functioning save() method and a pk and everything, which won't be the case here.

bendemboski commented 11 years ago

I committed some unit tests that reproduce this issue to https://github.com/bendemboski/django-tastypie-mongoengine/tree/Issue58.

mitar commented 11 years ago

Can you please make pull requests? It is easier to have an open pull request and then work on that. It is almost like issue, but with code. You can update pull request as we discuss as well, just by updating your branch from which you are doing a pull request, the pull request is then automatically updated.

ozexpert commented 10 years ago

I'm also having the same issue.