0

I am a junior developer from Greece and i need your help. In my django project, I have a model (Product) with a custom method(get_sale) that calculates a discount price after user inputs values . On my views ,there is a product list function that returns the products sorted as the user submits a form on a template. I managed to sort the data with the fields of the model Product as( price,created_date,..) but i can not find a way to sort the data in relation with the custom method get_sale().
It is difficult to me to understand the annotate method and how to apply on a custom method (attribute) of the model Product. Also i tried with lambda function but i cannot find a solution as i get "unsupported operand type(s) for -: 'int' and 'NoneType'".

class Product(models.Model):
    product_name    = models.CharField(max_length=200, unique=True)
    slug            = models.SlugField(max_length=200, unique=True)
    description     = models.TextField(max_length=500, blank=True)
    short_desc      = models.TextField(max_length=200, blank=True)
    length          = models.CharField(max_length=50, blank=True)
    height          = models.CharField(max_length=50, blank=True)
    depth           = models.CharField(max_length=50, blank=True)
    weight          = models.CharField(max_length=50, blank=True)
    composition     = models.TextField(max_length=500, blank=True)
    care            = models.TextField(max_length=500, blank=True)
    length_strap    = models.TextField(max_length=50, blank=True)
    handle          = models.TextField(max_length=50, blank=True)
    price           = models.DecimalField(max_digits = 5,decimal_places = 2)
    images          = models.ImageField(upload_to='images/products')
    stock           = models.IntegerField()
    is_available    = models.BooleanField(default=True)
    category        = models.ForeignKey(Category, on_delete=models.CASCADE)
    created_date    = models.DateTimeField(auto_now_add=True)
    modified_date   = models.DateTimeField(auto_now=True)
    code            = models.CharField(max_length=30,unique=True)
    discount_percentage = models.PositiveIntegerField(blank=True)

    def get_sale(self):
        price = self.price * (100 - self.discount_percentage) / 100
        return price

views.py

if temp == "discount_percentage":
                products = Product.objects.exclude(discount_percentage__lte=0).order_by("-discount_percentage")
            else:
                products = Product.objects.all().filter(is_available=True).order_by(get_sale) //not working
                #products= sorted(Product.objects.all(), key=lambda m: m.get_sale())

Finally i tried a different path which is to save the returned data from get_sale() to the database on a existing field(price) but with that way ,every time the user change the discount ,new price is calculated not on the default price of the product but on the latest price.

Please if you can guide me to find a solution. (Sorry for my bad english).

  • The lambda error seems to be caused by `100 - self.discount_percentage`. `self.discount_percentage` can be null/blank as defined in your model. – Brian Destura Feb 09 '22 at 00:59
  • How can i solve that?I set a default value and set to integer but it seems that is not the case. discount_percentage = models.IntegerField(blank=True,default=0). Also i removed the blank=true but no effect so maybe this is not error. discount_percentage = models.IntegerField(default=0) – George Bres Feb 09 '22 at 11:13

1 Answers1

0
products = Product.objects.annotate(
        discounted_price=ExpressionWrapper(
            F('price') * (100 - F('discount_percentage')) / 100,
            output_field=DecimalField(),
        )
    
products.filter(is_available=True).order_by('discounted_price')