将左外部联接查询转换为Django orm queryset/query

2024-09-30 06:33:31 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑到PostgreSQL 9.2.10、Django 1.8、Python2.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)

以及下面的原始查询,它准确地返回了我要查找的内容:

^{pr2}$

返回如下:

 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提供了一个使用有效的内部连接的解决方案。如果有人能破译这些乱七八糟的内联原始html,我可能已经找到了一个解决方案HERE。在

**编辑2**

有没有一种方法可以过滤字段(其中something='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已经提供了最完整的答案,使用了一个内部连接,但希望这个问题能够引发人们对如何实现这一目标的思考。由于这似乎不是天生的可能,任何和所有的建议都是受欢迎的,因为它们可能导致更好的解决办法。也就是说,用托多的回答,我能够完成我所需要的确切问题:

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()或任何原始查询代码。我完全愿意将模型更改为使用foreignkey,如果这有助于实现这一点,并且从性能的角度来看,这是最好的方法。我将使用与django-datatables-view一起返回的对象,如果这对设计有帮助的话。在


Tags: 方法iprestidapphostmodemodels
2条回答

我想这对你很有用!实际上,可以使用Q构造查询。 我在Django shell上尝试了一下,我创建了一些数据,然后我做了如下操作:

restProdAPI.objects.filter(Q(rest_host=s1.soap_host)|Q(rest_ip=s1.soap_ip))

其中s1是soaprodapi。在

这是我所有的代码,你可以试试看是否能帮到你

^{pr2}$

使用内部连接求解

如果您只能使用包含相应的restProdAPIrestProdAPI(根据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"]
)

如何过滤更多?

由于我们使用的是^{},我建议您仔细阅读文档。一般来说,我们不能将.filter用于selectdict中的某些字段,因为它们不是soapProdAPI的一部分,Django无法解析它们。我们必须坚持使用wherekwarg中的.extra,因为它是一个列表,所以我们最好再添加一个元素。在

^{pr2}$

重复子查询

如果你真的需要所有的soapProdAPI's,不管它们是否有对应的restProdAPI,我只能想到一个丑陋的例子,其中对你需要的每个字段重复一个subquery。在

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)"
    },
)

相关问题 更多 >

    热门问题