Как показать поля из другого сериализатора в Django rest framework

Я хочу показывать дополнительные поля в ответе, показывая похожие продукты или связанные продукты в категории, когда я нахожусь на странице подробного описания продукта. Например: Если я просматриваю страницу с подробным описанием одного товара и в нижней части страницы должен быть показан список сопутствующих товаров. Поэтому в ответе о сопутствующих товарах я хочу показатьhighest_offer_price, product_offer_discount, category_offer_discount из ProductDetailserilaizer.

#Serializer.py

class RelatedProductSerializer(ModelSerializer):

    class Meta:
        model = Products
        fields = ['product_name', 'slug', 'base_price', 'images']

class ProductDetailserializer(ModelSerializer):
    product_offer_discount = SerializerMethodField()
    category_offer_discount = SerializerMethodField()
    highest_offer_price = SerializerMethodField()
    description = ProductDescription()
    extra_images = SerializerMethodField()
    related_products = SerializerMethodField()

    class Meta:
        model = Products
        fields = [
            "id",
            "product_name",
            "slug",
            "highest_offer_price",
            "category_offer_discount",
            "product_offer_discount",
            "description",
            "base_price",
            "stock",
            "is_available",
            "images",
            "extra_images",
            "related_products"
        ]

    def to_representation(self, instance):
        print('INSTANCE', instance)
        rep = super().to_representation(instance)
        rep['description'] = ProductDescriptionSerializer(instance.description, many=True).data
        return rep

    def get_related_products(self, obj):
        products= Products.objects.filter(category=obj.category).exclude(id=obj.id)
        return RelatedProductSerializer(products, many=True, context=self.context).data

    def get_extra_images(self, obj):
        images = obj.extra_images.all()
        return ProductImageSerializer(images, many=True, context=self.context).data

#Views.py

class ProductDetailView(APIView):
    def get(self, request, category_slug, product_slug):
        try:
            single_product = Products.objects.get(
                category__slug=category_slug, slug=product_slug
            )
        except:
            raise exceptions.NotFoundError()
        serializer = ProductDetailserializer(
            single_product, context={
            "request": request, 
            }
            
        )
        return Response(serializer.data)

#Response

{
    "id": 1,
    "product_name": "Pendant 1",
    "slug": "pendant-1",
    "highest_offer_price": null,
    "category_offer_discount": null,
    "product_offer_discount": null,
    "description": [
        {
            "title": "First title",
            "description": "First description pendant 1"
        },
        {
            "title": "second title",
            "description": "second description pendant 1"
        }
    ],
    "base_price": 2500,
    "stock": 97,
    "is_available": true,
    "images": "http://127.0.0.1:8000/media/photos/products/pendant3.webp",
    "extra_images": [
        {
            "images": "http://127.0.0.1:8000/media/photos/product-images/pendant3.webp"
        },
        {
            "images": "http://127.0.0.1:8000/media/photos/product-images/pendant3_BQJRObf.webp"
        },
        {
            "images": "http://127.0.0.1:8000/media/photos/product-images/pendant3_QGmLbXC.webp"
        }
    ],
    "related_products": [
        {
            "product_name": "Pendant 2",
            "slug": "pendant-2",
            "base_price": 3500,
            "images": "http://127.0.0.1:8000/media/photos/products/pendant2.webp"
        },
        {
            "product_name": "Pendant 3",
            "slug": "pendant-3",
            "base_price": 1500,
            "images": "http://127.0.0.1:8000/media/photos/products/281031cw114n.webp"
        },
        {
            "product_name": "pendant 4",
            "slug": "pendant-4",
            "base_price": 1500,
            "images": "http://127.0.0.1:8000/media/photos/products/281031cw114n_Nxbx7lT.webp"
        }
    ]

Я новичок в этом и усложняю все слишком сильно, потому что я уже написал несколько сериализаторов для Product model.

Совершенно нормально иметь несколько сериализаторов для одной и той же модели, если данные в них различаются.

Если вы беспокоитесь о повторном написании одного и того же кода несколько раз на разных сериализаторах, вы всегда можете сделать базовый сериализатор для вашей модели Products и затем расширять его по мере необходимости.

Нравится:

# Make a BaseProductSerializer that inherits from Modelserializer and contains all fields and methods that all Products serializers need.
class BaseProductSerializer(Modelserializer):
    product_offer_discount = SerializerMethodField()
    category_offer_discount = SerializerMethodField()
    highest_offer_price = SerializerMethodField()

    def get_product_offer_discount(self):
        return # whatever this method should do...

    def get_category_offer_discount(self):
        return # whatever this method should do...

    def get_highest_offer_price(self):
        return # whatever this method should do...


# Make a serializer for related products that inherits from BaseProductSerializer and specify the Meta data.
class RelatedProductSerializer(BaseProductSerializer):
    class Meta:
        model = Products
        fields = [
            'product_name',
            'slug',
            'base_price',
            'images',
            'highest_offer_price',
            'product_offer_discount',
            'category_offer_discount'
        ]


# Make a serializer for product details that inherits from BaseProductSerializer and add any extra fields/methods that you need.
class ProductDetailserializer(BaseProductSerializer):
    description = ProductDescription()
    extra_images = SerializerMethodField()
    related_products = SerializerMethodField()

    class Meta:
        model = Products
        fields = [
            "id",
            "product_name",
            "slug",
            "highest_offer_price",
            "category_offer_discount",
            "product_offer_discount",
            "description",
            "base_price",
            "stock",
            "is_available",
            "images",
            "extra_images",
            "related_products"
        ]

    def to_representation(self, instance):
        print('INSTANCE', instance)
        rep = super().to_representation(instance)
        rep['description'] = ProductDescriptionSerializer(instance.description, many=True).data
        return rep

    def get_related_products(self, obj):
        products= Products.objects.filter(category=obj.category).exclude(id=obj.id)
        return RelatedProductSerializer(products, many=True, context=self.context).data

    def get_extra_images(self, obj):
        images = obj.extra_images.all()
        return ProductImageSerializer(images, many=True, context=self.context).data

Надеюсь, это поможет.

Вернуться на верх