假设有PostgreSQL 9.2.10,Django 1.8,python 2.7.5以及以下模型:
class restProdAPI(models.Model):
rest_id = models.PositiveIntegerField(primary_key=True)
rest_host = models.CharField(max_length=20)
rest_ip = models.GenericIPAddressField(default='0.0.0.0')
rest_mode = models.CharField(max_length=20)
rest_state = models.CharField(max_length=20)
class soapProdAPI(models.Model):
soap_id = models.PositiveIntegerField(primary_key=True)
soap_host = models.CharField(max_length=20)
soap_ip = models.GenericIPAddressField(default='0.0.0.0')
soap_asset = models.CharField(max_length=20)
soap_state = models.CharField(max_length=20)
以下是能够返回我所需要的内容的原始查询语句:
SELECT
app_restProdAPI.rest_id, app_soapProdAPI.soap_id, app_restProdAPI.rest_host, app_restProdAPI.rest_ip, app_soapProdAPI.soap_asset, app_restProdAPI.rest_mode, app_restProdAPI.rest_state
FROM
app_soapProdAPI
LEFT OUTER JOIN
app_restProdAPI
ON
((app_restProdAPI.rest_host = app_soapProdAPI.soap_host)
OR
(app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip))
WHERE
app_restProdAPI.rest_mode = 'Excluded';
这会返回如下结果:
rest_id | soap_id | rest_host | rest_ip | soap_asset | rest_mode | rest_state
---------+---------+---------------+----------------+------------+-----------+-----------
1234 | 12345 | 1G24019123ABC | 123.123.123.12 | A1234567 | Excluded | Up
使用Django的模型和ORM结构,最好的方法是什么?
我一直在寻找可能的方法来完全连接这两个表,但似乎没有干净或高效的方法来做到这一点。我也尝试了寻找在Django中进行左外连接的方法,但是文档稀少或难以理解。
我知道我可能需要使用Q对象来执行其中的or子句。此外,我已经查看了关系,看起来
foreignkey()
可能有效,但我不确定这是否是最佳方法。任何帮助都将不胜感激。提前谢谢您。**编辑1**
到目前为止,Todor提供了一个使用INNER JOIN的解决方案。如果有人能解密内联原始HTML的混乱,我可能已经找到了一个解决方案HERE。
**编辑2**
有没有一种方法可以像我上面的查询那样在一个字段上进行筛选(其中某些内容='something'),就像Todor的回答一样?我尝试了以下操作,但它仍然包括所有记录,即使我的等效postresql查询按预期工作。似乎我不能把所有东西都放在where中,因为当我删除其中一个or语句并只执行and语句时,它会应用排除过滤器。
soapProdAPI.objects.extra(
select = {
'rest_id' : 'app_restprodapi.rest_id',
'rest_host' : 'app_restprodapi.rest_host',
'rest_ip' : 'app_restprodapi.rest_ip',
'rest_mode' : 'app_restprodapi.rest_mode',
'rest_state' : 'app_restprodapi.rest_state'
},
tables = ['app_restprodapi'],
where = ['app_restprodapi.rest_mode=%s \
AND app_restprodapi.rest_host=app_soapprodapi.soap_host \
OR app_restprodapi.rest_ip=app_soapprodapi.soap_ip'],
params = ['Excluded']
)
** 编辑 3 / 已有解决方案 **
到目前为止,Todor 提供了最完整的答案,使用 INNER JOIN,但希望这个问题能引起思考,看看是否仍然可以完成。由于这似乎本质上不可能,因此欢迎任何建议,因为它们可能会带来更好的解决方案。话虽如此,使用 Todor 的答案,我能够实现我需要的确切查询:
restProdAPI.objects.extra(
select = {
'soap_id' : 'app_soapprodapi.soap_id',
'soap_asset' : 'app_soapprodapi.soap_asset'
},
tables = ['app_soapprodapi'],
where = ['app_restprodapi.rest_mode = %s',
'app_soapprodapi.soap_host = app_restprodapi.rest_host OR \
app_soapprodapi.soap_ip = app_restprodapi.rest_ip'
],
params = ['Excluded']
)
** TLDR **
我想将这个PostGreSQL查询转换为Django提供的ORM,完全不使用.raw()
或任何原始查询代码。如果从性能角度来看这是最好的方法,我完全可以改变模型,使其具有外键。如果这有助于设计,我将与django-datatables-view返回的对象一起使用。
INNER JOIN
而不是LEFT JOIN
?我可以用.extra
来展示一种方法,但查询结果更像是在你的例子中使用了INNER JOIN
。 - Todor