Django rest框架如何创建3个嵌套序列化器对象? [英] Django rest framework how to create 3 nested-serializer objects?

查看:68
本文介绍了Django rest框架如何创建3个嵌套序列化器对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试根据文档.

这是我的models.py:

this my models.py :

from django.db import models


class Request(models.Model):
    origin = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return str(self.id)


class RequestOrders(models.Model):
    request_id = models.ForeignKey(Request, related_name='request_orders', on_delete=models.DO_NOTHING, blank=True, null=True)
    position = models.CharField(max_length=255, blank=True)
    destination = models.CharField(max_length=255, blank=True)
    order_ref = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return self.id


class RequestOrderItemss(models.Model):
    request_order_id = models.ForeignKey(RequestOrders, related_name='request_order_itemss', on_delete=models.DO_NOTHING, blank=True, null=True)
    product_id = models.ForeignKey('product.Product', on_delete=models.DO_NOTHING, blank=True, null=True)
    qty = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return self.id

这是我的serializers.py:

Here's my serializers.py :

from rest_framework import serializers
from request.models import Request, RequestOrders, RequestOrderItemss
from product.serializers import ProductSerializer


class RequestOrderItemssSerializer(serializers.ModelSerializer):
    class Meta:
        model = RequestOrderItemss
        fields = ('id', 'request_order_id', 'product_id', 'qty')


class RequestOrdersSerializer(serializers.ModelSerializer):
    request_order_itemss = RequestOrderItemssSerializer(many=True)

    class Meta:
        model = RequestOrders
        fields = ('id', 'request_id', 'position', 'destination', 'order_ref', 'request_order_itemss')


class RequestSerializer(serializers.ModelSerializer):
    request_orders = RequestOrdersSerializer(many=True)

    class Meta:
        model = Request
        fields = ('id', 'origin', 'request_orders')

    def create(self, validated_data):
        request_orders_data = validated_data.pop('request_orders')
        request = Request.objects.create(**validated_data)
        for request_order_data in request_orders_data:
            request_order_items_data = request_order_data.pop('request_order_itemss')
            request_order = RequestOrders.objects.create(request_id=request,
                                                                        **request_order_data)
            for request_order_item_data in request_order_items_data:
                RequestOrderItemss.objects.create(request_order_id=request_order,
                                                         **request_order_item_data)
        return request

    def update(self, instance, validated_data):
        request_orders_data = validated_data.pop('request_orders')
        orders = instance.request_orders.all()
        orders = list(orders)
        instance.origin = validated_data.get('origin', instance.origin)
        instance.save()

        for request_order_data in request_orders_data:
            request_order_items_data = request_order_data.pop('request_order_itemss')
            items = instance.request_orders.get().request_order_itemss.all()
            items = list(items)
            for request_order_item_data in request_order_items_data:
                item = items.pop(0)
                item.product_id = request_order_item_data.get('product_id', item.product_id)
                item.qty = request_order_item_data.get('qty', item.qty)
                item.save()
            order = orders.pop(0)
            order.position = request_order_data.get('position', order.position)
            order.destination = request_order_data.get('destination', order.destination)
            order.order_ref = request_order_data.get('order_ref', order.order_ref)
            order.save()
        return instance

这是我的views.py

and this is my views.py

from django.http import JsonResponse
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from request.models import Request, RequestOrders, RequestOrderItemss
from request.serializers import RequestSerializer, RequestOrdersSerializer, \
    RequestOrderItemssSerializer


class RequestListView(generics.ListCreateAPIView):
    queryset = Request.objects.all()
    serializer_class = RequestSerializer
    permission_classes = (IsAuthenticated,)


class RequestView(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = RequestSerializer
    queryset = Request.objects.all()
    permission_classes = (IsAuthenticated,)


class RequestOrdersListView(generics.ListCreateAPIView):
    queryset = RequestOrders.objects.all()
    serializer_class = RequestOrdersSerializer
    permission_classes = (IsAuthenticated,)


class RequestOrdersView(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = RequestOrdersSerializer
    queryset = RequestOrders.objects.all()
    permission_classes = (IsAuthenticated,)


class RequestOrderItemssListView(generics.ListCreateAPIView):
    queryset = RequestOrderItemss.objects.all()
    serializer_class = RequestOrderItemssSerializer
    permission_classes = (IsAuthenticated,)


class RequestOrderItemssView(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = RequestOrderItemssSerializer
    queryset = RequestOrderItemss.objects.all()
    permission_classes = (IsAuthenticated,)

这是我要保存在数据库中的JSON数据:

this is my JSON data that i want to save in data base :

{
"origin": "Krishna Rungta",
"request_orders": [
    {
        "position":"2",
        "destination" :"Paris",
        "order_ref":"ref#123",
        "request_order_itemss":[
            {
                "product_id":4,
                "qty":444,
            }
            {
                "product_id":5,
                "qty":33,
            }
        ]
    }
    {
        "position":"3",
        "destination" :"Paris",
        "order_ref":"ref#124",
        "request_order_itemss":[
            {
                "product_id":6,
                "qty":123,
            }
            {
                "product_id":4,
                "qty":54,
            }
        ]
    }
]

}

当我尝试在邮递员上进行测试时,出现此错误:

when I try to test this on Postman I get this error :

禁止直接分配给相关集的背面.改用request_order_itemss.set().

Direct assignment to the reverse side of a related set is prohibited. Use request_order_itemss.set() instead.

所以我想知道问题出在哪里,我做的是对的还是不对的.

So I want to know where is the problem and is what i did is right or is there something wrong.

推荐答案

错误

这里的问题是您有一个双重嵌套的模型,但是实际上您只是在尝试创建对象之前反序列化了其中的一层.您已经创建了 RequestOrderItemssSerializer RequestOrdersSerializer 类,但实际上并没有在 create 方法中使用它们.如果将给定的JSON对象发布到/requests/端点,则视图将使用相同的对象调用 RequestSerializer.create .然后,在您的 create 方法中,使用例如

The error

The problem here is that you have a twice-nested model, but you are only actually deserializing one layer of it before trying to create the objects. You have created RequestOrderItemssSerializer and RequestOrdersSerializer classes, but you are not actually using them in the create method. If you POST the given JSON object to the /requests/ endpoint, the view will call RequestSerializer.create with the that same object. In your create method, you will then call RequestOrders.objects.create with, e.g.,

request_order_data = {
    "position":"2",
    "destination" :"Paris",
    "order_ref":"ref#123",
    "request_order_itemss": [
        {
            "product_id":4,
            "qty":444,
        }
        {
            "product_id":5,
            "qty":33,
        }
    ]
}

如您所见,列表 request_order_itemss 尚未正确反序列化,并且尚未创建商品,这就是为什么您会收到有关尝试将值直接分配给表格的反面的错误的原因 RequestOrderItemss.request_order_id ForeignKey 关系.

As you can see, the list request_order_itemss has not been properly deserialized and the items have not been created, which is why you are getting the error about trying to directly assign values to the reverse side of the RequestOrderItemss.request_order_id ForeignKey relationship.

请注意,您在文档中所指向的示例旨在向您展示如何处理这一确切错误,但仅适用于单个层次结构(为给定专辑创建单独的曲目).

Note that the example you pointed to in the docs is designed to show you how to handle this exact error, but only for a single level of hierarchy (creating the individual tracks for a given album).

解决此问题的最简单方法是取消 RequestOrderSerializer RequestOrderItemsSerializer ,而只向 Request.create 处理第二个嵌套部分的方法.像这样:

The simplest way to solve this, is to do away with the RequestOrderSerializer and RequestOrderItemsSerializer and just add an inner loop to the Request.create method which handles the second nested part. Something like this:

class RequestSerializer(serializers.ModelSerializer):
    ...

    def create(self, validated_data):
        request_orders_data = validated_data.pop('request_orders')
        request = Request.objects.create(**validated_data)
        for request_order_data in request_orders_data:
            ro_items = request_order_data.pop('request_order_itemss')
            order = RequestOrders.objects.create(request_id=request, **request_order_data)
            for ro_item in ro_items:
                RequestOrderItemss.create(request_order_id=order, **ro_item)
        return request

我不会实现和测试它,因此这里编写的代码中可能存在错误,但是概念应该足够简单.我也只处理过 create 方法,但是您应该可以按扩展名处理 update .

I won't implement and test this, so there are probably bugs in the code as written here, but the concept should be straightforward enough. I've also only handled the create method, but you should be able to treat update by extension.

这篇关于Django rest框架如何创建3个嵌套序列化器对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆