I have product serializer
which return category_offer_price
& product_offer_price
,
before getting this response I want to compare both price and only return whichever is highest price.
#Serilaizer.py
class ProductSerializer(ModelSerializer):
category = CategorySerializer()
product_offer_price = SerializerMethodField()
category_offer_price = SerializerMethodField()
class Meta:
model = Products
fields = [
"id",
"product_name",
"slug",
"category",
"description",
"category_offer_price",
"product_offer_price",
"base_price",
"stock",
"is_available",
"created_date",
"images",
"images_two",
"images_three",
]
def get_product_offer_price(self, obj):
try:
product_offer = ProductOffer.objects.get(product=obj)
if product_offer.is_active:
offer_price = product_offer.product_offer_price()
return offer_price
except Exception:
pass
return None
def get_category_offer_price(self, obj):
try:
category_offer = CategoryOffer.objects.get(category=obj.category)
if category_offer.is_active:
offer_price = category_offer.category_offer_price(obj)
return offer_price
except Exception:
pass
return None
#Models.py
class Products(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
product_name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(max_length=100, unique=True)
description = models.TextField(max_length=500)
base_price = models.IntegerField()
images = models.ImageField(upload_to="photos/products")
images_two = models.ImageField(upload_to="photos/products")
images_three = models.ImageField(upload_to="photos/products")
stock = models.IntegerField()
is_available = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Products"
def __str__(self):
return self.product_name
I'd like to know is it possible to compare serializer fields in a serializer class?
CodePudding user response:
You can override to_representation()
Example:
class ProductSerializer(ModelSerializer):
category = CategorySerializer()
product_offer_price = SerializerMethodField()
category_offer_price = SerializerMethodField()
...
...
def to_representation(self, instance):
data = super().to_representation(instance)
# access required fields like this
product_offer_price = data['product_offer_price']
category_offer_price = data['category_offer_price']
# do calculations here and returning the desired field as `calculated_price`
if category_offer_price > product_offer_price:
data['calculated_price'] = category_offer_price
else:
data['calculated_price'] = product_offer_price
return data
CodePudding user response:
You can move into one method, to validate your field. Also, substitute your try:except with get-object-or-404 method and your serializer fields with all value since you are using everything, to have a much cleaner code.
from django.shortcuts import get_object_or_404
class ProductSerializer(ModelSerializer):
category = CategorySerializer()
price = SerializerMethodField()
class Meta:
model = Products
fields = '__all__'
def get_price(self, obj):
product_offer = get_object_or_404(ProductOffer, product=obj)
category_offer = get_object_or_404(CategoryOffer, category=obj.category)
if product_offer.is_active and category_offer.is_active:
if product_offer.product_offer_price() > category_offer.category_offer_price(obj):
return product_offer.product_offer_price()
else:
return category_offer.category_offer_price(obj)
elif product_offer.is_active and not category_offer.is_active:
return product_offer.product_offer_price()
elif category_offer.is_active and not product_offer.is_active:
return category_offer.category_offer_price(obj)
EDIT: As you can see I used the classic if/else in this solution, although since Python 3.10 you can use the Match case statement to substitute these conditions chain.