【问题标题】:Django rest framework how to create 3 nested-serializer objects?Django rest框架如何创建3个嵌套序列化器对象?
【发布时间】:2020-04-11 05:51:13
【问题描述】:

我正在尝试根据docs 在 Django Rest Framework 中创建嵌套对象。

这是我的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 :

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

这是我的观点.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 数据:

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

}

当我尝试在 Postman 上进行测试时,我得到了这个错误:

禁止直接分配到相关集的反面。 请改用 request_order_itemss.set()。

所以我想知道问题出在哪里,我所做的是对还是有什么问题。

【问题讨论】:

  • 欢迎来到 StackOverflow。使用完整的堆栈跟踪进行调试会更容易。另外,这些“正在加载...”模型在哪里?我很难理解对LoadingRequestloading_request_order_itemss 等的引用。也就是说,我猜你看到的问题是因为你实际上没有调用嵌套的 create 方法(在RequestSerializer 中,您只需创建RequestOrders 对象,而无需先反序列化已验证的数据)。
  • apa yang terjadi 在你的模型上,LoadingRequestOrders 和 LoadingRequest???
  • @RishiG 抱歉,我编辑了模型并进行了一些更改,但我忘记更改所有内容,但我不知道问题出在哪里。你能给我解释一下吗?
  • 您仍然可以在RequestSerializer 中调用LoadingRequest.objects.create,并且您也没有按照我的建议提供实际的堆栈跟踪,但我想我已经解决了这个问题并将回答为尽我所能

标签: django django-rest-framework nested postman


【解决方案1】:

错误

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

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 @ 的反面时收到错误消息987654332@关系。

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

简单的解决方案

解决这个问题的最简单方法是取消RequestOrderSerializerRequestOrderItemsSerializer,只需在处理第二个嵌套部分的Request.create 方法中添加一个内部循环。像这样的:

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

【讨论】:

  • 我创建了更新方法,但我收到此错误“get() 返回了多个 RequestOrders -- 它返回了 2!”当我尝试更新多个 Request_Order 时(当我只更新一个时它起作用)。我编辑我的序列化程序以查看我创建它的更新方法。你能帮帮我吗?
  • 这里不适合它。使用代码和完整的堆栈跟踪发布一个新问题。有关如何提出好问题的建议,请参阅 this article
猜你喜欢
  • 1970-01-01
  • 2022-06-25
  • 2018-12-13
  • 2020-07-07
  • 2013-05-05
  • 2021-06-23
  • 2019-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多