Skip to content

Instantly share code, notes, and snippets.

@MacMaru
Created December 10, 2012 09:53
Show Gist options
  • Save MacMaru/4249666 to your computer and use it in GitHub Desktop.
Save MacMaru/4249666 to your computer and use it in GitHub Desktop.
Custom save_m2m for Django Tastypie to pass in request.user
def save_m2m(self, bundle):
"""
Handles the saving of related M2M data.
Due to the way Django works, the M2M data must be handled after the
main instance, which is why this isn't a part of the main ``save`` bits.
Currently slightly inefficient in that it will clear out the whole
relation and recreate the related data as needed.
"""
for field_name, field_object in self.fields.items():
if not getattr(field_object, 'is_m2m', False):
continue
if not field_object.attribute:
continue
if field_object.blank:
continue
if field_object.readonly:
continue
# Get the manager.
related_mngr = getattr(bundle.obj, field_object.attribute)
through_class = getattr(related_mngr, 'through', None)
if through_class and not through_class._meta.auto_created:
# ManyToMany with an explicit intermediary table.
# This should be handled by with specific code, so continue
# without modifying anything.
# NOTE: this leaves the bundle.needs_save set to True
continue
related_bundles = bundle.data[field_name]
# Remove any relations that were not POSTed
if through_class:
# ManyToMany with hidden intermediary table.
# Use the manager to clear out the relations.
related_mngr.clear()
else:
# OneToMany with foreign keys to this object.
# Explicitly delete objects to pass in the user.
posted_pks = [b.obj.pk for b in related_bundles if b.obj.pk]
if self._meta.pass_request_user_to_django:
for obj in related_mngr.for_user(
user=bundle.request.user).exclude(pk__in=posted_pks):
obj.delete(user=bundle.request.user)
else:
for obj in related_mngr.all().exclude(pk__in=posted_pks):
obj.delete()
# Save the posted related objects
related_objs = []
for related_bundle in related_bundles:
related_objs.append(related_bundle.obj)
if related_bundle.needs_save:
if self._meta.pass_request_user_to_django:
related_bundle.obj.save(user=bundle.request.user)
else:
related_bundle.obj.save()
related_bundle.needs_save = False
if through_class:
# ManyToMany with hidden intermediary table. Since the save
# method on a hidden table can not be overridden we can use the
# related_mngr to add.
related_mngr.add(*related_objs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment