Сепарация ответа в DRF

Я возвращаю сводку заказов, в которой order_total, order_number ,quantity and the payment повторяется, но я хочу, чтобы она была показана только один раз. Например, все товары должны быть только одни во вложенном ответе сериализатора, а другие должны быть показаны по одному без повторений

#Serializer

class OrderSummarySerializer(ModelSerializer):
    product = ProductSerializer()
    payment = PaymentSerializer()
    order_number = SerializerMethodField()
    order_total = SerializerMethodField()

    class Meta:
        model = OrderProducts
        fields = ["order_number", "payment", "product", "quantity", "order_total"]

    def get_order_total(self, obj):
        return obj.order.order_total

    def get_order_number(self, obj):
        print(obj)
        return obj.order.order_number

#Просмотры

class OrderSummary(APIView):
    def get(self, request):
        try:
            order_number = request.GET.get("order_number")
            orders = Orders.objects.get(user=request.user, order_number=order_number)
            order_summary = OrderProducts.objects.filter(
                user=request.user, order__order_number=order_number, is_ordered=True
            )

            context = {
                "request": request,
            }
            serializer = OrderSummarySerializer(
                order_summary, many=True, context=context
            )
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            print(e)
            return Response(
                {"error": "Something went wrong"}, status=status.HTTP_400_BAD_REQUEST

#Ответ я получаю

[
    {
        "order_number": "ypVtT1",
        "payment": {
            "payment_method": "cod",
            "amount_paid": "",
            "status": "Pending",
            "created_at": "2022-12-16T16:46:30.915646+05:30"
        },
        "product": {
            "id": 1,
            "product_name": "Pendant1",
            "sub_product_name": null,
            "slug": "pendant-1",
            "highest_offer_price": 250.0,
            "category_offer_discount": 1250.0,
            "product_offer_discount": 2250.0,
            "base_price": 2500,
            "stock": 5,
            "is_available": true,
            "product_image": "http://127.0.0.1:8000/media/photos/products/pendant3.webp"
        },
        "quantity": 1,
        "order_total": 2170.0
    },
    {
        "order_number": "ypVtT1",
        "payment": {
            "payment_method": "cod",
            "amount_paid": "",
            "status": "Pending",
            "created_at": "2022-12-16T16:46:30.915646+05:30"
        },
        "product": {
            "id": 2,
            "product_name": "Pendant2",
            "sub_product_name": null,
            "slug": "pendant-2",
            "highest_offer_price": 1750.0,
            "category_offer_discount": 1750.0,
            "product_offer_discount": null,
            "base_price": 3500,
            "stock": 11,
            "is_available": true,
            "product_image": "http://127.0.0.1:8000/media/photos/products/pendant2.webp"
        },
        "quantity": 1,
        "order_total": 2170.0
    }
]

# Ответ, который я хочу получить:

[
  {
     "order_number": "ypVtT1",
    "quantity": 1,
     "order_total": 2170.0
        "payment": {
            "payment_method": "cod",
            "amount_paid": "",
            "status": "Pending",
            "created_at": "2022-12-16T16:46:30.915646+05:30"
        },
        "product": {
            "id": 1,
            "product_name": "Pendant1",
            "sub_product_name": null,
            "slug": "pendant-1",
            "highest_offer_price": 250.0,
            "category_offer_discount": 1250.0,
            "product_offer_discount": 2250.0,
            "base_price": 2500,
            "stock": 5,
            "is_available": true,
            "product_image": "http://127.0.0.1:8000/media/photos/products/pendant3.webp"
        },
    
    },
        "product": {
            "id": 2,
            "product_name": "Pendant2",
            "sub_product_name": null,
            "slug": "pendant-2",
            "highest_offer_price": 1750.0,
            "category_offer_discount": 1750.0,
            "product_offer_discount": null,
            "base_price": 3500,
            "stock": 11,
            "is_available": true,
            "product_image": "http://127.0.0.1:8000/media/photos/products/pendant2.webp"
        },
        
    }
]

Это из-за использования ModelSerializer. Должен ли я сделать отдельный сериализатор для отдельных вещей, чтобы показать их и вызвать его на текущем сериализаторе?

Вы можете создать Order Serializer, который содержит OrderSummary, вот так:

class OrderSerializer(serializer.ModelSerializer):
    summary = serializer.SerializerMethodField()
    
    class Meta:
         model = Order
        fields = ["order_number", "summary", "order_total"]

    def get_summary(self, obj):
       order_summary = OrderProducts.objects.filter(
                user=obj.user, order__order_number=obj.order_number, is_ordered=True
            )  # consider using reverse query in Django queryset
       serializer = OrderSummarySerializer(
                order_summary, many=True, context=self.context
            )
       return serializer.data

Затем используйте его в представлениях следующим образом:

class OrderSummary(APIView):
    def get(self, request):
        try:
            order_number = request.GET.get("order_number")
            order = Order.objects.get(user=request.user, order_number=order_number)
            return OrderSerializer(instance=order, context={'request':request}).data
        except:
           ....
Вернуться на верх