serializers.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. from __future__ import print_function, unicode_literals
  2. from rest_framework.serializers import ListSerializer
  3. __all__ = [
  4. 'BulkListSerializer',
  5. 'BulkSerializerMixin',
  6. ]
  7. class BulkSerializerMixin(object):
  8. def to_internal_value(self, data):
  9. ret = super(BulkSerializerMixin, self).to_internal_value(data)
  10. id_attr = getattr(self.Meta, 'update_lookup_field', 'id')
  11. request_method = getattr(getattr(self.context.get('view'), 'request'), 'method', '')
  12. # add update_lookup_field field back to validated data
  13. # since super by default strips out read-only fields
  14. # hence id will no longer be present in validated_data
  15. if all((isinstance(self.root, BulkListSerializer),
  16. id_attr,
  17. request_method in ('PUT', 'PATCH'))):
  18. id_field = self.fields[id_attr]
  19. id_value = id_field.get_value(data)
  20. ret[id_attr] = id_value
  21. return ret
  22. class BulkListSerializer(ListSerializer):
  23. update_lookup_field = 'id'
  24. def update(self, instances, all_validated_data):
  25. id_attr = getattr(self.child.Meta, 'update_lookup_field', 'id')
  26. all_validated_data_by_id = {
  27. i.pop(id_attr): i
  28. for i in all_validated_data
  29. }
  30. updated_objects = []
  31. for obj in instances:
  32. obj_id = getattr(obj, id_attr, None)
  33. obj_validated_data = all_validated_data_by_id.get(obj_id)
  34. if obj_id and obj_validated_data:
  35. # use model serializer to actually update the model
  36. # in case that method is overwritten
  37. updated_objects.append(self.child.update(obj, obj_validated_data))
  38. return updated_objects