Django REST Framework批量更新字典列表API报错求助
问题:批量更新Waitlist记录时收到400 Bad Request错误
错误详情
HTTP 400 Bad Request
Allow: PUT, OPTIONS
Content-Type: application/json
Vary: Accept[
{
"non_field_errors": [
"Expected a list of items but got type "dict"."
]
},
{
"non_field_errors": [
"Expected a list of items but got type "dict"."
]
}
]
传入的JSON数据
[ { "id": "1", "order": "5" }, { "id": "2", "order": "3" } ]
相关代码
Waitlist模型
class Waitlist(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50, blank=True) identification = models.CharField(max_length=50) email = models.EmailField(max_length=100, validators=[], blank=True) mobile_phone = PhoneNumberField(blank=True) store_number = models.PositiveSmallIntegerField() order = models.PositiveSmallIntegerField() status = models.PositiveSmallIntegerField() created = models.DateTimeField(auto_now_add=True) def __str__(self): return self.first_name + ' ' + self.last_name
views.py核心代码
from django.shortcuts import render, get_object_or_404 from rest_framework.response import Response from rest_framework.decorators import api_view from rest_framework import status from .models import Waitlist from .serializers import WaitlistOrderSerializer, WaitlistOrderListSerializer @api_view(['PUT']) def waitlistOrder(request): waitlist_data = request.data waitlist = [] for data in waitlist_data: waitlist_id = data.get('id') w = Waitlist.objects.get(id=waitlist_id) waitlist.append(w) serializer = WaitlistOrderListSerializer( waitlist, data=waitlist_data, many=True) if serializer.is_valid(): serializer.save() return Response({'success': 'Waitlist order updated successfully'}) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py核心代码
class WaitlistOrderSerializer(serializers.Serializer): id = serializers.IntegerField() order = serializers.IntegerField() def update(self, instance, validated_data): instance.order = validated_data.get('order', instance.order) instance.save() return instance class WaitlistOrderListSerializer(serializers.ListSerializer): child = WaitlistOrderSerializer() def update(self, instances, validated_data): for instance, data in zip(instances, validated_data): self.child.update(instance, data) return instances
解决方案
错误核心原因是:你已经自定义了WaitlistOrderListSerializer作为列表序列化器,但在视图初始化序列化器时额外传递了many=True参数,导致DRF重复解析,把每个字典数据当成列表处理,从而抛出类型不匹配的错误。
1. 修复序列化器初始化代码
移除many=True参数:
serializer = WaitlistOrderListSerializer(waitlist, data=waitlist_data)
2. 优化实例查询逻辑
- 改用
get_object_or_404避免ID不存在时抛出未捕获的异常:w = get_object_or_404(Waitlist, id=waitlist_id) - 批量查询实例减少数据库请求次数,同时保证顺序匹配:
waitlist_ids = [data.get('id') for data in waitlist_data] # 批量查询 waitlist_queryset = Waitlist.objects.filter(id__in=waitlist_ids) # 按传入ID的顺序排序实例 waitlist = sorted(waitlist_queryset, key=lambda x: waitlist_ids.index(str(x.id)))
3. 增加事务保证原子性
在列表序列化器的update方法中添加事务,确保批量更新操作要么全部成功,要么全部回滚:
from django.db import transaction class WaitlistOrderListSerializer(serializers.ListSerializer): child = WaitlistOrderSerializer() @transaction.atomic def update(self, instances, validated_data): for instance, data in zip(instances, validated_data): self.child.update(instance, data) return instances
内容的提问来源于stack exchange,提问作者cbirch
相关产品推荐
相关产品推荐

