如何比较两个序列化器字段并显示较高的那个在django rest

bjp0bcyl  于 2022-11-26  发布在  Go
关注(0)|答案(3)|浏览(101)

我有product serializer,它返回category_offer_priceproduct_offer_price,在得到这个响应之前,我想比较两个价格,只返回最高的价格。

序列化器.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

型号.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

我想知道是否可以比较序列化程序类中的序列化程序字段?

f1tvaqid

f1tvaqid1#

您可以覆盖to_representation()
示例:

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
mum43rcc

mum43rcc2#

你可以使用一个方法来验证你的字段。另外,用get-object-or-404方法替换try:except,用allvalue替换序列化器字段,因为你使用了所有的方法,这样代码就更简洁了。

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)

编辑:正如您所看到的,我在这个解决方案中使用了经典的if/else,尽管从Python3.10开始,您可以使用Match case statement来替换这些条件链。
如果对象不存在:

class ProductSerializer(ModelSerializer):
    category = CategorySerializer()
    price = SerializerMethodField()

    class Meta:
        model = Products
        fields = '__all__'

    def get_price(self, obj):
        try:
            product_offer = ProductOffer.objects.filter(product=obj).first()
            category_offer = CategoryOffer.objects.filter(category=obj.category).first()
                
            if not product_offer and not category_offer:
                return obj.base_price            
            elif not category_offer:  
                return product_offer.product_offer_price()            
            elif not product_offer:
                return category_offer.category_offer_price(obj)                   
            elif category_offer and product_offer:
                if category_offer.is_active and not product_offer.is_active:
                    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 product_offer.is_active:
                    if category_offer.category_offer_price(obj) > product_offer.product_offer_price():
                        return category_offer.category_offer_price(obj)
                    else:
                        return product_offer.product_offer_price()
        except:
            return obj.base_price

不过,老实说,如果没有对象,则is_active字段是多余的。

wh6knrhe

wh6knrhe3#

不确定这是否是您想要的,但您可以使用SerializerMethodField类型的字段,它允许您添加一个计算字段,您可以调用category_offer_higher_price。其值由返回最高值的函数计算。请参见以下链接:https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

相关问题