I have the following model structure below:
class Master(models.Model):
name = models.CharField(max_length=50)
mounting_height = models.DecimalField(max_digits=10,decimal_places=2)
class MLog(models.Model):
date = models.DateField(db_index=True)
time = models.TimeField(db_index=True)
sensor_reading = models.IntegerField()
m_master = models.ForeignKey(Master)
The goal is to produce a queryset that returns all the fields from MLog plus a calculated field (item_height) based on the related data in Master
using Django's raw sql:
querySet = MLog.objects.raw('''
SELECT a.id,
date,
time,
sensor_reading,
mounting_height,
(sensor_reading - mounting_height) as item_height
FROM db_mlog a JOIN db_master b
ON a.m_master_id = b.id
''')
How do I code this using Django's ORM?
I can think of two ways to go about this without relying on
raw()
. The first is pretty much the same as what @tylerl suggested. Something like this:In this case I am defining a custom (derived) property for
MLog
calleditem_height
. This property is calculated as the difference of thesensor_reading
of an instance and the mounting_height of its related master instance. More onproperty
here.You can then do something like this:
The second way to do this is to use the
extra()
method and have the database do the calculation for you.You'll note the use of
select_related()
. Without this theMaster
table will not be joined with the query and you will get an error.I always do the calculations in the app rather than in the DB.
Then you can manipulate it just as you would any other field, and it does whatever you defined with the underlying data. For example:
Property, by the way, is just a standard property decorator, in this case coded as follows (I don't remember where it came from):