我正在使用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.data
CreateAPIView
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
)