0

我正在使用django-treebeard 批量创建load_bulk)一堆嵌套在这种格式的列表中的项目:

items = [
    {
        "data": {"item_id": i1.id},
    },
    {
        "data": {"item_id": i2.id},
    },
    {
        "data": {"item_id": i3.id},
    },
]
payload = {"list_id": l1.id, "items": items}

这是我的models.py:

class List(MP_Node):
    item = models.ForeignKey(Item, null=True, blank=True)

我的意见.py:

class ListParentBulkCreateView(generics.CreateAPIView):
    queryset = List.objects.all()
    serializer_class = ListBulkCreateSerializer
    permission_classes = [AllowAny]

我的序列化程序.py:

class ListBulkCreateSerializer__data(serializers.ModelSerializer):
    item_id = serializers.UUIDField(required=True)

    class Meta:
        model = List
        fields = ["item_id"]

class ListBulkCreateSerializer_itemsWrapper(serializers.ModelSerializer):
    data = ListBulkCreateSerializer__data()
    
    class Meta:
        model = List
        fields = ["data"]

class ListBulkCreateSerializer(serializers.ModelSerializer):
    list_id = serializers.UUIDField(required=True)
    items = serializers.ListField(
        child=ListBulkCreateSerializer_itemsWrapper(), write_only=True
    )
    
    class Meta:
        model = List
        fields = ["list_id", "items"]

    def create(self, validated_data):
        # My code fails on is_valid() so
        # this doesn't even run
        list_id = validated_data["list_id"]
        list = List.objects.get(id=list_id)
        items = validated_data("items")
        # create tree
        List.load_bulk(items, parent=list)
        return {"list_id": list_id}
    

但是当我尝试通过序列化程序创建时出现 400 错误。是serializer.error

{'parents': {0: {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}, 1: {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}, 2: {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}}}

当我分解CreateAPIView'create方法时,它显示序列化程序正在将我的对象列表转换为字符串列表:

class ListParentBulkCreateView(generics.CreateAPIView):
    ...

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        print(serializer.is_valid())
        print(serializer.errors)
        data = serializer.data
        print("0", data, type(data))
        print("1", data["parents"], type(data["parents"]))
        print("2", data["parents"][0], type(data["parents"][0]))
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )

回报:

False
{'parents': {0: {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}, 1: {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}, 2: {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}}}
0 <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
1 <class 'list'>
2 <class 'str'>

为什么会这样?我可以确认我的初始有效载荷是正确的:

print(payload["items"][0] # <class 'dict'>

编辑:

因此,经过大量试验和错误,如果我是json.dump我的初始代码,payload然后在我的方法中,我的代码就可以工作json.load了......request.dataCreateAPIView create

但究竟为什么这是必要的呢?


items = [
    {
        "data": {"item_id": str(i1.id)},
    },
    {
        "data": {"item_id": str(i2.id)},
    },
    {
        "data": {"item_id": str(i3.id)},
    },
]
payload = {"list_id": str(l1.id), "items": items}

视图.py

class ListParentBulkCreateView(generics.CreateAPIView):
    ...

    def create(self, request, *args, **kwargs):
        data = json.loads(request.data)
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )
4

0 回答 0