简体   繁体   中英

Calculated field based on method inside Django model

How do I automatically populate a field in my PurchaseOrder model:

class PurchasedOrder(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.IntegerField()


    @property
    def batch_cost(self):
        return self.quantity * self.product.unit_price

    def __str__(self):
        return self.product.name

If I define it as a property, I won't be able to use this property to filter and stuff. I want it to be a calculated field.

I tried the following but it didn't work:

def calculate_batch_cost(self):
    return self.quantity * self.product.unit_price

batch_cost = models.FloatField(default=calculate_batch_cost)

I will appreciate your help <3

You can .annotate(..) [Django-doc] it in a QuerySet , like:

from django.db.models import F

PurchasedOrder.objects.annotate(
    
).filter(
    batch_cost__gt=100  # An example of filtering
)

The PurchasedOrder s from this queryset will have an attribute .batch_cost that is the unit_price of the product, times the quantity .

We can then for example filter on that one. For example in the above query, we will get all PurchasedOrder s with a batch_cost that is greater than 100 .

If this field need to be specified and change anytime the object is created or updated, then you can add it inside the save funtion:

def save(self, *args, **kwargs):
    self.batch_cost = self.calculate_batch_cost()
    super(PurchasedOrder, self).save(*args, **kwargs)

And of course, you need to add the field inside the model

batch_cost = models.FloatField()

Then you can still use you calculate_batch_cost function elsewhere in you code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM