-
Notifications
You must be signed in to change notification settings - Fork 106
/
Copy pathserializers.py
70 lines (50 loc) · 2.31 KB
/
serializers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
from __future__ import print_function, unicode_literals
import inspect
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import ListSerializer
__all__ = [
'BulkListSerializer',
'BulkSerializerMixin',
]
class BulkSerializerMixin(object):
def to_internal_value(self, data):
ret = super(BulkSerializerMixin, self).to_internal_value(data)
id_attr = getattr(self.Meta, 'update_lookup_field', 'id')
request_method = getattr(getattr(self.context.get('view'), 'request'), 'method', '')
# add update_lookup_field field back to validated data
# since super by default strips out read-only fields
# hence id will no longer be present in validated_data
if all((isinstance(self.root, BulkListSerializer),
id_attr,
request_method in ('PUT', 'PATCH'))):
id_field = self.fields[id_attr]
id_value = id_field.get_value(data)
ret[id_attr] = id_value
return ret
class BulkListSerializer(ListSerializer):
update_lookup_field = 'id'
def update(self, queryset, all_validated_data):
id_attr = getattr(self.child.Meta, 'update_lookup_field', 'id')
all_validated_data_by_id = {
i.pop(id_attr): i
for i in all_validated_data
}
if not all((bool(i) and not inspect.isclass(i)
for i in all_validated_data_by_id.keys())):
raise ValidationError('')
# since this method is given a queryset which can have many
# model instances, first find all objects to update
# and only then update the models
objects_to_update = queryset.filter(**{
'{}__in'.format(id_attr): all_validated_data_by_id.keys(),
})
if len(all_validated_data_by_id) != objects_to_update.count():
raise ValidationError('Could not find all objects to update.')
updated_objects = []
for obj in objects_to_update:
obj_id = getattr(obj, id_attr)
obj_validated_data = all_validated_data_by_id.get(obj_id)
# use model serializer to actually update the model
# in case that method is overwritten
updated_objects.append(self.child.update(obj, obj_validated_data))
return updated_objects