Попытка массового обновления списка приоритетов - DRF
Я пытаюсь массово обновить весь свой список приоритетов. Вот модель:
class OrderPriority(models.Model):
order = models.OneToOneField(Order, related_name='priority_order', on_delete=models.CASCADE)
priority = models.BigIntegerField(unique=True)
Вот мой Bulk Update Serializer и List Serializer Class:
class BulkPriorityUpdateListSerializer(serializers.ListSerializer):
def update(self, instances, validated_data):
instance_hash = {index: instance for index, instance in enumerate(instances)}
result = [
self.child.update(instance_hash[index], attrs)
for index, attrs in enumerate(validated_data)
]
writable_fields = [
x
for x in self.child.Meta.fields
if x not in self.child.Meta.read_only_fields
]
try:
self.child.Meta.model.objects.bulk_update(result, writable_fields)
except IntegrityError as e:
raise ValidationError(e)
return result
def to_representation(self, instances):
rep_list = []
for instance in instances:
rep_list.append(
dict(
id=instance.id,
order=instance.order.id,
priority=instance.priority,
)
)
return rep_list
class BulkOrderPrioritySerializer(serializers.ModelSerializer):
class Meta:
model = OrderPriority
fields = ("id", "order", "priority")
read_only_fields = ("id",)
list_serializer_class = BulkPriorityUpdateListSerializer
Вот мое представление вместе с пользовательским представлением массового обновления:
class CustomBulkUpdateAPIView(generics.UpdateAPIView):
def update(self, request, *args, **kwargs):
def validate_ids(data, field="id", unique=True):
if isinstance(data, list):
id_list = [int(x[field]) for x in data]
if unique and len(id_list) != len(set(id_list)):
raise ValidationError("Multiple updates to a single {} found".format(field))
return id_list
return [data]
ids = validate_ids(request.data)
instances = self.get_queryset(ids=ids)
serializer = self.get_serializer(
instances, data=request.data, partial=False, many=True
)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
class OrderPriorityUpdateAPIView(CustomBulkUpdateAPIView):
serializer_class = BulkOrderPrioritySerializer
def get_queryset(self, ids=None):
return OrderPriority.objects.filter(
id__in=ids,
)
Затем я отправляю массовый запрос PUT с телом:
[
{
"id": 1,
"priority": 1,
"order": 109
},
{
"id": 2,
"priority": 2,
"order": 110
},
{
"id": 3,
"priority": 3,
"order": 111
},
{
"id": 4,
"priority": 4,
"order": 112
},
{
"id": 5,
"priority": 5,
"order": 113
}
]
Затем я получаю ошибку:
Я следовал руководству по массовому обновлению из здесь, и я также использовал его раньше без проблем. Не уверен, что именно вызывает проблему. Похоже, проблема возникает, когда я проверяю .is_valid. Может быть, я неправильно передаю данные? Может быть, дело в том, что приоритет - это уникальное поле? Любая помощь будет принята с благодарностью.
Думаю, это относится к https://github.com/miki725/django-rest-framework-bulk/issues/68
По сути, я думаю, что проблема заключается в том, что дочерний сериализатор пытается выполнить проверку на весь QuerySet, проверяя наличие pk.
Ваш QuerySet не содержит pk; однако каждый экземпляр QuerySet содержит его.
Решением является переписывание метода to_internal_value() в классе ListSerializer для передачи каждого экземпляра по одному в child.serializer и запуск проверки:
self.child.instance = self.instance.get(id=item['id']) if self.instance else None
self.child.initial_data = item
validated = self.child.run_validation(item)
Надеюсь, это поможет