Converting LEFT OUTER JOIN query to Django orm queryset/query

后端 未结 2 1093
我寻月下人不归
我寻月下人不归 2021-02-10 00:19

Given PostgreSQL 9.2.10, Django 1.8, python 2.7.5 and the following models:

class restProdAPI(models.Model):
    rest_id = models.PositiveIntegerField(primary_ke         


        
相关标签:
2条回答
  • 2021-02-10 00:31

    Solving it with INNER JOIN

    In case you can go with only soapProdAPI's that contain corresponding restProdAPI ( in terms of your join statement -> linked by host or ip). You can try the following:

    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"]
    )
    

    How to filter more?

    Since we are using .extra I would advice to read the docs carefully. In general we can't use .filter with some of the fields inside the select dict, because they are not part of the soapProdAPI and Django can't resolve them. We have to stick with the where kwarg in .extra, and since it's a list, we better just add another element.

        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']
    

    Repeated subquery

    If you really need all soapProdAPI's no matter if they have corresponding restProdAPI I can only think of a one ugly example where a subquery is repeated for each field you need.

    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)"
        },
    )
    
    0 讨论(0)
  • 2021-02-10 00:48

    I think this could be usefull for you! Effectively, you can use Q to construct your query. I try it the Django shell, I create some data and I did something like this:

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

    Where s1 is a soapProdAPI.

    This is all the code i whote, you can try it and to see if can help you

    from django.db.models import Q
    from core.models import restProdAPI, soapProdAPI
    
    s1 =  soapProdAPI.objects.get(soap_id=1)
    
    restProdAPI.objects.filter(Q(rest_id=s1.soap_id)|Q(rest_ip=s1.soap_ip))
    
    0 讨论(0)
提交回复
热议问题