21
class PO(models.Model)
    qty = models.IntegerField(null=True)
    cost = models.IntegerField(null=True)
    total = qty * cost

How will I solve total = qty * cost above. I know it will cause an error, but have no idea of how to deal with this.

Peter Pudaite
  • 406
  • 8
  • 18
rechie
  • 2,139
  • 5
  • 25
  • 38

2 Answers2

38

You can make total a property field, see the docs

class PO(models.Model)
    qty = models.IntegerField(null=True)
    cost = models.IntegerField(null=True)

    def _get_total(self):
       "Returns the total"
       return self.qty * self.cost
    total = property(_get_total)
Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
Ahsan
  • 11,516
  • 12
  • 52
  • 79
  • Is there any way we can make it as a calculation of qty and cost? – rechie Jul 13 '12 at 06:40
  • `total` will behave like a field, you can access it through class object like other fields. – Ahsan Jul 13 '12 at 06:46
  • 3
    The problem with this though is that you can't access total through a queryset... :( – Michael Mar 29 '14 at 11:33
  • 3
    Nor does this help if the value is something that it resource-intensive to compute, and you only want to do it when other fields are changed. If you're not using an actual field, there is no simple way to store the computed value in the database. – brianmearns Sep 12 '14 at 16:43
  • Nor is the field visible in `PO._meta.get_fields()`. Other calculated fields such as `GenericRelation` will be listed there. An approach that inherits from `django.forms.fields.Field` would be very desirable! – filip Dec 01 '15 at 20:17
  • @FilipDalüge Thanks for you your suggestion. Please go ahead and edit the answer or your can post your own. – Ahsan Dec 02 '15 at 08:22
16

Justin Hamades answer

class PO(models.Model)
    qty = models.IntegerField(null=True)
    cost = models.IntegerField(null=True)

    @property
    def total(self):
        return self.qty * self.cost
Community
  • 1
  • 1
rechie
  • 2,139
  • 5
  • 25
  • 38
  • 1
    What's wrong with the @ahsan's answer, its exactly what you need? – Ahsan Jul 19 '12 at 04:53
  • And this is subtly wrong, since total is not a property, it's a method. – datashaman Jan 22 '13 at 17:51
  • 3
    @MarlinForbes isnt `total = property(_get_total) identical` to `@property`? Check [here](http://www.artima.com/weblogs/viewpost.jsp?thread=240808). – agconti Aug 22 '13 at 15:38
  • 1
    @agconti Yes its result is total the same. Thanks for the reference. It helped me understand more about decorators. – rechie Dec 27 '13 at 01:59
  • It helped me to use decorators confidently, rather than calling a function as argument of a function. We who are new in python usually prefer using Ahsan's answer. This is a powerful feature of Python. – rechie Dec 27 '13 at 02:17
  • Hi is it possible to initialize the property total in some cases when you create an object using the get_or_create method? What I meant to say is if the get_or_create method inputs a value for total, it should take this value. Otherwise it should calculate the value using the total method – Arun Jan 08 '19 at 17:18
  • This is not working if you want the property accessible directly in the QuerySet (ie before data rendering). You may want to sort on the total or export the data in a spreadsheet for example. In that case your total won't be displayed! As mentioned [here](https://stackoverflow.com/a/42491803/7639622), **QuerySet methods call the database directly, circumventing the django Model.** In that case you could either use annotate in the get_queryset method or use the excellent django-computed-property app! You could also create a Db View containing your fields (django-database-view app). – openHBP Oct 17 '19 at 10:45