bea*_*gle 5 python sql django orm django-models
给定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)
Run Code Online (Sandbox Code Playgroud)
以下原始查询返回的正是我要寻找的内容:
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';
Run Code Online (Sandbox Code Playgroud)
返回如下:
rest_id | soap_id | rest_host | rest_ip | soap_asset | rest_mode | rest_state
---------+---------+---------------+----------------+------------+-----------+-----------
1234 | 12345 | 1G24019123ABC | 123.123.123.12 | A1234567 | Excluded | Up
Run Code Online (Sandbox Code Playgroud)
使用Django的模型和orm结构进行这项工作的最佳方法是什么?
我一直在寻找可能完全没有关系地连接两个表的方法,但是似乎没有一种干净有效的方法。我也尝试过寻找在django中进行左外部联接的方法,但是文档仍然很少或难以破译。
我知道我可能必须使用Q对象来执行我在那里的or子句。另外,我已经研究了关系,并且看起来foreignkey()可能可行,但是我不确定这是否是最好的方法。任何和所有帮助将不胜感激。先感谢您。
** 编辑1 **
到目前为止,Todor提供了使用有效的INNER JOIN的解决方案。如果有人可以破译在线原始html的混乱局面,我可能会在这里找到解决方案。
** 编辑2 **
有没有办法像我上面给出的查询(Todor的答案)那样对字段(某物=“某物”)进行过滤?我尝试了以下操作,但是即使我的等效postresql查询按预期工作,它仍包含所有记录。似乎我无法在所需要的地方拥有所有内容,因为当我删除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']
)
Run Code Online (Sandbox Code Playgroud)
** 编辑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']
)
Run Code Online (Sandbox Code Playgroud)
** TLDR **
我想将此PostGreSQL查询转换为Django提供的ORM,而无需使用.raw()或任何原始查询代码。如果这样做很方便,并且从性能的角度来看,这是最好的方法,那么我完全愿意将模型更改为具有外键。如果在设计方面有帮助,我将使用与django-datatables-view一起返回的对象。
如果您只能使用soapProdAPI's包含相应的内容restProdAPI (根据您的 join 语句 -> 由主机或 ip 链接)。您可以尝试以下操作:
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_host = app_soapProdAPI.soap_host \
OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip"]
)
Run Code Online (Sandbox Code Playgroud)
如何过滤更多?
由于我们正在使用,.extra我建议仔细阅读文档。一般来说,我们不能使用dict.filter中的某些字段select,因为它们不是 dict 的一部分soapProdAPI,并且 Django 无法解析它们。我们必须坚持使用where kwargin .extra,因为它是一个列表,所以我们最好添加另一个元素。
where = ["app_restProdAPI.rest_host = app_soapProdAPI.soap_host \
OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip",
"app_restProdAPI.rest_mode=%s"
],
params = ['Excluded']
Run Code Online (Sandbox Code Playgroud)
如果你真的需要所有,soapProdAPI's无论它们是否有对应的,restProdAPI我只能想到一个丑陋的例子,其中 asubquery为你需要的每个字段重复。
soapProdAPI.objects.extra(
select = {
'rest_id' : "(select rest_id from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
'rest_host' : "(select rest_host from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
'rest_ip' : "(select rest_ip from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
'rest_mode' : "(select rest_mode from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)",
'rest_state': "(select rest_state from app_restProdAPI where app_restProdAPI.rest_host = app_soapProdAPI.soap_host OR app_restProdAPI.rest_ip = app_soapProdAPI.soap_ip)"
},
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3795 次 |
| 最近记录: |