【问题标题】:REST Framework — Serializing many-to-many. Create and SaveREST 框架——序列化多对多。创建并保存
【发布时间】:2021-06-20 20:51:59
【问题描述】:

我正在为我的 API 使用 django-restframework。

我的问题:我无法验证数据。需要创建“区域”并与 courier 嵌套。区域作为 json 列表发送。

但在验证数据时,出现以下错误: error_valid {'regions': [{'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]}, {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]}, {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]

如何使用这个 json POST 请求创建模型?

POST json:

{
"data": [
{
"courier_id": 10,
"courier_type": "foot",
"regions": [1, 12, 22]
},
{
"courier_id": 11,
"courier_type": "bike",
"regions": [22]
},..
]
}

我的models.py:

class Regions(models.Model):
    region_id = models.PositiveIntegerField(unique=True)

    def __str__(self):
        return self.region_id


class Courier(models.Model):
    courier_id = models.PositiveIntegerField(unique=True,
                                             )
    courier_type = models.CharField(max_length=4,
                                    choices=TypeCourier.choices,
                                    blank=False,
                                    )
    regions = models.ManyToManyField("Regions",
                                     through=RegionsCouriers,
                                     through_fields=("courier",
                                                     "region"
                                                     ),
                                     )

需要与发布请求一起创建区域 我的序列化器.py

class RegionsSerializer(serializers.ModelSerializer):

    class Meta:
        fields = "__all__"
        model = Regions


class CourierSerializerPost(serializers.ModelSerializer):
    regions = RegionsSerrializer(many=True)

    class Meta:
        model = Courier
        fields = "__all__"

我的视图.py

class CourierView(APIView):

    def post(self, request):
        data = request.data["data"]
        couriers_add = []
        couriers_fail = []
        for record in data:
            serializer = CourierSerializerPost(data=record)
            if serializer.is_valid():
                courier_id = record["courier_id"]
                couriers_add.append({"id": courier_id})
                serializer.save()
            else:
                couriers_fail.append({"id": record["courier_id"]})
        if couriers_fail:
            return Response({"couriers": couriers_fail},
                        status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response({"couriers": couriers_add},
                            status=status.HTTP_201_CREATED
                            )

请帮帮我 升级版: 我如何将验证区域字段更改为列表正整数字段。 我的错误:我无法创建: record {'courier_id': 12, 'courier_type': 'car', 'regions': [12, 22, 23, 33]}

serializer.is_valid False

serializer.error {'regions': [{'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]},

【问题讨论】:

    标签: python django serialization django-rest-framework m2m


    【解决方案1】:

    您不能像使用外键或一对一那样使用序列化程序来保存 M2M 字段。

    你需要重写序列化器的create方法并指定M2M添加

    class CourierSerializerPost(serializers.ModelSerializer):
        regions = RegionsSerrializer(many=True)
    
        class Meta:
            model = Courier
            fields = "__all__"
    
        def create(self, validated_data):
            # removing the regions ids from the about to be created Courier obj
            regions_ids = validated_data.pop('regions', None)
            # getting the regions objs
            regions = tuple(Regions.objects.filter(id__in=regions_ids))
            # creating the Courier object
            obj = Courier.objects.create(**validated_data)
            # adding the regions relations to it
            obj.regions.add(*regions)
            return obj
    

    【讨论】:

    • 感谢您的帮助,提供方法覆盖的提示),但我在验证时遇到了这个问题(我无法创建:record {'courier_id': 12, 'courier_type': 'car', 'regions': [12, 22, 23, 33]} serializer.is_valid False serializer.error {'regions': [{'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got int.', code='invalid')]}, 就像 - 我无法验证来自字段“区域”的数据"
    • 如何将验证区域字段更改为列表正整数字段