Python Django rest框架错误断言错误'child'是必需的参数
在开发应用程序时,我遇到了一个问题Python Django rest框架错误断言错误'child'是必需的参数,python,django,django-rest-framework,Python,Django,Django Rest Framework,在开发应用程序时,我遇到了一个问题 AssertionError at /api/update/ `child` is a required argument. Request Method: GET Request URL: http://45.56.80.77/api/update/?token=1234567&ifloorplan=2 Django Version: 3.0.6 Exception Type: AssertionError Exception Value:
AssertionError at /api/update/
`child` is a required argument.
Request Method: GET
Request URL: http://45.56.80.77/api/update/?token=1234567&ifloorplan=2
Django Version: 3.0.6
Exception Type: AssertionError
Exception Value:
`child` is a required argument.
Exception Location: /root/Env/ifloorplan/lib/python3.8/site-packages/rest_framework/serializers.py in __init__, line 591
Python Executable: /usr/local/bin/uwsgi
Python Version: 3.8.2
Python Path:
['.',
'',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/root/Env/ifloorplan/lib/python3.8/site-packages']
Server time: Mon, 1 Jun 2020 07:18:31 +0000
也就是说,我试图在数据库中更新并创建这种记录
[
{
"id": 2,
"level": [
{
"id": 2,
"plan_level": {
"img": null,
"img_height": null,
"img_width": null,
"position_x": null,
"position_y": null,
"level": null
},
"images": [
{
"id": 2,
"cam": [
{
"id": 2,
"ken_burns": {
"effect": null,
"start_pos_x": null,
"start_pos_y": null,
"finish_pos_x": null,
"finish_pos_y": null,
"start_width": null,
"start_height": null,
"finish_width": null,
"finish_height": null,
"cam": null
},
"rotation": 0.34,
"pos_x": 21.0,
"pos_y": 234.0,
"width": 1234.0,
"height": 234.0,
"img": 2
},
{
"id": 3,
"ken_burns": {
"effect": null,
"start_pos_x": null,
"start_pos_y": null,
"finish_pos_x": null,
"finish_pos_y": null,
"start_width": null,
"start_height": null,
"finish_width": null,
"finish_height": null,
"cam": null
},
"rotation": 4.0,
"pos_x": 354.0,
"pos_y": 345.0,
"width": 345.0,
"height": 345.0,
"img": 2
}
],
"img": "/media/ifloorplans_source/test.jpg",
"level": 2
}
],
"tabLabel": "1 st",
"plan": 2
}
],
"textColor": "WQ2123",
"bgColor": "SA2132",
"camColor": "CV1234",
"author": 14
}
]
这是我的serializer.py
from django.contrib.auth.models import User
from .models import (
IFloorPlan,
Level,
PlanImg,
Image,
Cam,
KenBurns,
)
from rest_framework import serializers
class KenBurnsSerializer(serializers.ListSerializer):
# plan = IFloorPlanSerializer(required=True)
def update(self, instance, validated_data):
pass
def create(self, validated_data):
predictions = [KenBurns(**item) for item in validated_data]
return KenBurns.objects.bulk_create(predictions)
class Meta:
model = KenBurns
fields = '__all__'
class CamSerializer(serializers.ListSerializer):
ken_burns = KenBurnsSerializer()
def update(self, instance, validated_data):
pass
def create(self, validated_data):
predictions = [Cam(**item) for item in validated_data]
return Cam.objects.bulk_create(predictions)
class Meta:
model = Cam
fields = '__all__'
class ImageSerializer(serializers.ListSerializer):
cam = CamSerializer(many=True)
def update(self, instance, validated_data):
pass
def create(self, validated_data):
predictions = [Image(**item) for item in validated_data]
return Image.objects.bulk_create(predictions)
class Meta:
model = Image
fields = '__all__'
class PlanImgSerializer(serializers.ListSerializer):
# plan = IFloorPlanSerializer(required=True)
def update(self, instance, validated_data):
pass
def create(self, validated_data):
predictions = [PlanImg(**item) for item in validated_data]
return PlanImg.objects.bulk_create(predictions)
class Meta:
model = PlanImg
fields = '__all__'
class LevelSerializer(serializers.ListSerializer):
plan_level = PlanImgSerializer()
images = ImageSerializer(many=True)
def update(self, instance, validated_data):
pass
def create(self, validated_data):
predictions = [Level(**item) for item in validated_data]
return Level.objects.bulk_create(predictions)
class Meta:
model = Level
fields = '__all__'
class IFloorPlanSerializer(serializers.Serializer):
level = LevelSerializer(many=True)
class Meta:
list_serializer_class = LevelSerializer
model = IFloorPlan
fields = '__all__'
views.py
from django.shortcuts import render
from django.http.response import JsonResponse
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import IFloorPlanSerializer
from rest_framework.views import APIView
from .models import IFloorPlan
from public.models import ApiToken
# Create your views here.
@api_view(['GET', ])
def get_ifloorplan(request):
if "token" in request.GET and "ifloorplan" in request.GET:
token_obj = ApiToken.objects.filter(token=request.GET["token"])
if token_obj:
plans = IFloorPlan.objects.filter(id=request.GET["ifloorplan"])
serializer = IFloorPlanSerializer(plans, many=True)
return Response(serializer.data)
else:
return JsonResponse({"message": "Don't valid token"}, status=status.HTTP_400_BAD_REQUEST)
else:
return JsonResponse({"message": "Don't valid GET parameter"}, status=status.HTTP_400_BAD_REQUEST)
@api_view(['PUT', 'GET',])
def update_ifloorplan(request):
if "token" in request.GET and "ifloorplan" in request.GET:
token_obj = ApiToken.objects.filter(token=request.GET["token"])
if token_obj:
plans = IFloorPlan.objects.filter(id=request.GET["ifloorplan"])
serializer = IFloorPlanSerializer(plans, data=request.data, many=True)
if serializer.is_valid():
serializer.save()
return JsonResponse({"message": "Update successful"}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return JsonResponse({"message": "Don't valid token"}, status=status.HTTP_400_BAD_REQUEST)
else:
return JsonResponse({"message": "Don't valid GET parameter"}, status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST', 'GET'])
def create_ifloorplan(request):
if "token" in request.GET:
token_obj = ApiToken.objects.get(token=request.GET["token"])
if token_obj:
plans = IFloorPlan(author=token_obj.user)
serializer = IFloorPlanSerializer(plans, data=request.data, many=True)
if serializer.is_valid():
serializer.save()
return JsonResponse({"message": "Create successful"}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return JsonResponse({"message": "Don't valid token"}, status=status.HTTP_400_BAD_REQUEST)
else:
return JsonResponse({"message": "Don't valid GET parameter"}, status=status.HTTP_400_BAD_REQUEST)
models.py
from django.db import models
from django.contrib.auth.models import User
class IFloorPlan(models.Model):
textColor = models.CharField(max_length=10, blank=True, null=True)
bgColor = models.CharField(max_length=10, blank=True, null=True)
camColor = models.CharField(max_length=10, blank=True, null=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
class Level(models.Model):
plan = models.ForeignKey(IFloorPlan, on_delete=models.CASCADE, related_name='level', blank=True, null=True)
tabLabel = models.CharField(max_length=100, blank=True, null=True)
class PlanImg(models.Model):
level = models.ForeignKey(Level, on_delete=models.CASCADE, related_name='plan_level', blank=True, null=True)
img = models.ImageField(upload_to='ifloorplans_source/', blank=True, null=True)
img_height = models.FloatField(blank=True, null=True)
img_width = models.FloatField(blank=True, null=True)
position_x = models.FloatField(blank=True, null=True)
position_y = models.FloatField(blank=True, null=True)
class Image(models.Model):
level = models.ForeignKey(Level, on_delete=models.CASCADE, related_name='images', blank=True, null=True)
img = models.ImageField(upload_to='ifloorplans_source/', blank=True, null=True)
class Cam(models.Model):
rotation = models.FloatField(blank=True, null=True)
pos_x = models.FloatField(blank=True, null=True)
pos_y = models.FloatField(blank=True, null=True)
img = models.ForeignKey(Image, on_delete=models.CASCADE, related_name='cam', blank=True, null=True)
width = models.FloatField(blank=True, null=True)
height = models.FloatField(blank=True, null=True)
class KenBurns(models.Model):
cam = models.ForeignKey(Cam, on_delete=models.CASCADE, related_name='ken_burns', blank=True, null=True)
effect = models.BooleanField(default=False, blank=True, null=True)
start_pos_x = models.FloatField(blank=True, null=True)
start_pos_y = models.FloatField(blank=True, null=True)
finish_pos_x = models.FloatField(blank=True, null=True)
finish_pos_y = models.FloatField(blank=True, null=True)
start_width = models.FloatField(blank=True, null=True)
start_height = models.FloatField(blank=True, null=True)
finish_width = models.FloatField(blank=True, null=True)
finish_height = models.FloatField(blank=True, null=True)
第二天我就解决不了这个问题了
起初,有一个无法更新多个表的问题。所以我决定使用列表序列化程序来更新和创建表中的记录。我很乐意提供任何帮助ListSerializer基本上是其他序列化程序的容器,只能包含一个特定的序列化程序,它被设置为“子”序列化程序 您的
LevelSerializer
扩展了ListSerializer,但未提供this子属性。这通常不是使用ListSerializer的方法-仅在非常特殊的情况下才需要扩展ListSerializer。在常见情况下,您需要为级别
模型创建一个普通的序列化程序,并将其设置为一个带有many=True
作为参数的字段。这将在引擎盖下创建一个列表序列化程序,如中所述
你犯了好几次错误,但这应该让你朝着正确的方向开始:
class-LevelSerializer(serializers.ModelSerializer)
类元:
模型=级别
字段=('plan','tabLabel')
类IFloorPlanSerializer(serializers.Serializer):
level=LevelSerializer(many=True)
要扩展列表序列化程序并提供自定义更新方法,请执行以下操作:
class LevelListSerializer(serializers.ListSerializer):
child = LevelSerializer()
def update(self, instance, validated_data):
# instance is the queryset, validated_data a list of dicts
# See [the documentation](https://github.com/encode/django-rest-framework/blob/master/docs/api-guide/serializers.md#customizing-multiple-update) for an example.
class IFloorPlanSerializer(serializers.Serializer):
level = LevelListSerializer()
我按照你写的那样做了,但遇到了另一个问题“many=True的序列化程序默认情况下不支持多个更新,只支持多个create。对于更新,不清楚如何处理插入和删除。如果需要支持多个更新,请使用
ListSerializer
类并重写.update()
这样您就可以准确地指定行为了。”我在错误断言errorchild
之前遇到的错误是一个必需的参数。我添加了这个参数,当接收数据时,我得到一个错误,``TypeError at/api/get/'Level'对象是不可编辑的```