简体   繁体   English

Django rest 框架错误 AssertionError `child` 是必需的参数

[英]Django rest framework error AssertionError `child` is a required argument

when developing my application I ran into a problem在开发我的应用程序时遇到了问题

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

that is, I tried to update and create in the database a record of this kind也就是说,我尝试在数据库中更新并创建这种记录

[
    {
        "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
    }
]

here is my serializer.py这是我的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视图.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模型.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)


I can't solve this problem already the second day At first there was a problem with the inability to update multiple tables.我已经无法在第二天解决这个问题 起初存在无法更新多个表的问题。 So I decided to use the list serializer to update and create records in the table.所以我决定使用列表序列化器来更新和创建表中的记录。 I will be glad of any help我会很高兴得到任何帮助

A ListSerializer is basically a container for other serializers and can only contain one specific serializer, which is set as it's "child" serializer. ListSerializer 基本上是其他序列化程序的容器,并且只能包含一个特定的序列化程序,该序列化程序被设置为它的“子”序列化程序。

Your LevelSerializer extends ListSerializer but does not provide a this child attribute.您的LevelSerializer扩展了 ListSerializer 但不提供 this 子属性。 This is typically not the way to use a ListSerializer - extending it is only needed for very special cases.这通常不是使用 ListSerializer 的方式——仅在非常特殊的情况下才需要扩展它。 In the common case, you want create a normal serializer for the Level model and set it as a field with many=True as argument.在常见情况下,您希望为Level model 创建一个普通的序列化程序,并将其设置为一个以many=True作为参数的字段。 This will create a list serializer under the hood as described in in the documentation这将在引擎盖下创建一个列表序列化程序,如文档中所述

You make the mistake several times, but this should get you started in the right direction:您多次犯错,但这应该让您朝着正确的方向开始:

class LevelSerializer(serializers.ModelSerializer)
    class Meta:
        model = Level
        fields = ('plan', 'tabLabel')

class IFloorPlanSerializer(serializers.Serializer):
    level = LevelSerializer(many=True)

To extend the list serializer and provide a custom update method:要扩展列表序列化程序并提供自定义更新方法:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM