Как показать поля из другого сериализатора в 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
Надеюсь, это поможет.