我有以下模型结构:
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)
Run Code Online (Sandbox Code Playgroud)
目标是生成一个查询集,该查询集根据Master中的相关数据返回MLog中的所有字段以及计算字段(item_height)
使用Django的原始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
''')
Run Code Online (Sandbox Code Playgroud)
我如何使用Django的ORM编写代码?
我可以想到两种不依赖的方法raw().第一个与@tylerl 建议的几乎相同.像这样的东西:
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)
def _get_item_height(self):
return self.sensor_reading - self.m_master.mounting_height
item_height = property(_get_item_height)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我正在为MLog被调用定义一个自定义(派生)属性item_height.此属性计算为sensor_reading实例与其相关主实例的mounting_height 的差异.更多关于property 这里.
然后你可以做这样的事情:
In [4]: q = MLog.objects.all()
In [5]: q[0]
Out[5]: <MLog: 2010-09-11 8>
In [6]: q[0].item_height
Out[6]: Decimal('-2.00')
Run Code Online (Sandbox Code Playgroud)
第二种方法是使用该extra()方法并让数据库为您进行计算.
In [14]: q = MLog.objects.select_related().extra(select =
{'item_height': 'sensor_reading - mounting_height'})
In [16]: q[0]
Out[16]: <MLog: 2010-09-11 8>
In [17]: q[0].item_height
Out[17]: Decimal('-2.00')
Run Code Online (Sandbox Code Playgroud)
你会注意到使用select_related().如果没有这个,Master表将不会与查询连接,您将收到错误.