关于使用DRF时报错{"non_field_errors":["Invalid data. Expected a dictionary, but got list."]}的解决...

问题描述:
原来的接口是接收单条json数据的,现在需要改变为一次性接收到多条数据,数据格式如下 :

[
{...},
{...},
...
]

其实就是由原来传一个{},改为了将多个{}放入一个list中然后将list传过去

各部分代码:
viewsets:

class OSSAccountRequestViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
serializer_class = OSSAccountRequestSerializer
queryset = OSSAccountRequest.objects.all()

serializer:

class OSSAccountSerializer(serializers.ModelSerializer):

class Meta:
model = OSSAccount
fields = ('cluster_code', 'cluster_name', 'account')


class OSSAccountRequestSerializer(serializers.ModelSerializer):

account_list = OSSAccountSerializer(many=True)
#account_list = serializers.PrimaryKeyRelatedField(queryset=OSSAccount.objects.all(), many=True)
#account_list = serializers.SlugRelatedField(many=True, read_only=True, slug_field='account')
#account_list = serializers.RelatedField(queryset=OSSAccount.objects.all(), many=True)

class Meta:
model = OSSAccountRequest
fields = '__all__'
#read_only_fields = ('account_list',)
#depth = 1

def create(self, validated_data):
logger.debug("search: ", validated_data)
account_data = []
if 'account_list' in validated_data:
account_data = validated_data.pop('account_list')

request_obj = OSSAccountRequest.objects.create(**validated_data)
for one_account in account_data:
OSSAccount.objects.create(request=request_obj, **one_account)
return request_obj

报错:
当传入数据为list时报错:

{"non_field_errors":["Invalid data. Expected a dictionary, but got list."]}

心路历程:
这部分主要讲述我解决问题的过程,想要答案可跳过,直接看结尾。
由于对框架比较陌生,这个问题上我绕了很多弯路,以上注释均是弯路上留下的,每一条都是泪呀。拿到这个问题,我首先看了Django Rest Framework的官方文档,文档上说ModelSerializer本身就是支持多条数据的create的,但不支持update,只需要加上many=true就可以了,看到这个的时候我已经欲哭无泪了,这many原来的代码上就加着啊,无奈之下我只好在网上寻找各种解决方法,很多都是像我注释的一样,在serializer中各种改。经历过无数次失败后,我在create函数中输入了logger.debug("serache:", validated_data"),终于,真相大白了。

解决方法:
其实我打印log只是想看看validated_data里面的数据到底是什么样的,但令我惊奇的是什么都没有打出来,连空行都没有,也就是说程序根本没有执行到这里,在viewsets中校验数据时就已经报错了,于是我查看了viewsets中关于接收数据格式的规定,并且在stackoverflow上找到了解决方案,只需将viewsets中的create方法覆盖掉即可。

class OSSAccountRequestViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
serializer_class = OSSAccountRequestSerializer
queryset = OSSAccountRequest.objects.all()

def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data, many=isinstance(request.data, list))
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return HttpResponse(json.dumps(serializer.data, ensure_ascii=False), content_type="application/json")
serializer = self.get_serializer(data=request.data, many=isinstance(request.data, list))

many=isinstance(request.data, list))使得接口可以接受单个的json数据,也可以接受list。

转载于:https://www.cnblogs.com/fxm1/p/11544381.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值