Constructing Django filter queries dynamically with args and kwargs

后端 未结 3 1777
独厮守ぢ
独厮守ぢ 2020-12-12 23:54

I\'m constructing some Django filter queries dynamically, using this example:

kwargs = { \'deleted_datetime__isnull\': True }
args = ( Q( title__icontains =         


        
相关标签:
3条回答
  • 2020-12-13 00:07

    you have list of Q class objects,

    args_list = [Q1,Q2,Q3]   # Q1 = Q(title__icontains='Foo') or Q1 = Q(**{'title':'value'})  
    args = Q()  #defining args as empty Q class object to handle empty args_list
    for each_args in args_list :
        args = args | each_args
    
    query_set= query_set.filter(*(args,) ) # will excute, query_set.filter(Q1 | Q2 | Q3)
    # comma , in last after args is mandatory to pass as args here
    
    0 讨论(0)
  • 2020-12-13 00:13
    firstQ = [
        Q(...),
        Q(...),
        Q(...)
    ]
    import functools
    functools.reduce(lambda a, b: a & b, Qrelationship)
    

    Or in my case, I needed to AND to different sets of filters:

    firstQ = [
        Q(...),
        Q(...),
        Q(...)
    ]
    secondQ = [
        Q(...),
        Q(...),
        Q(...)
    ]
    import functools
    combined = functools.reduce(lambda a, b: a | b, [
        functools.reduce(lambda a, b: a & b, firstQ),
        functools.reduce(lambda a, b: a & b, secondQ)
    ])
    myqueryset = Model.objects.filter(combined)
    # Make sure you apply the Q's first (BEFORE any other filter) or it will fail silently
    
    0 讨论(0)
  • 2020-12-13 00:28

    You can iterate it directly using a kwarg format (I don't know the proper term)

    argument_list = [] #keep this blank, just decalring it for later
    fields = ('title') #any fields in your model you'd like to search against
    query_string = 'Foo Bar' #search terms, you'll probably populate this from some source
    
    for query in query_string.split(' '):  #breaks query_string into 'Foo' and 'Bar'
        for field in fields:
            argument_list.append( Q(**{field+'__icontains':query_object} ) ) 
    
    query = Entry.objects.filter( reduce(operator.or_, argument_list) )
    
    # --UPDATE-- here's an args example for completeness
    
    order = ['publish_date','title'] #create a list, possibly from GET or POST data
    ordered_query = query.order_by(*orders()) # Yay, you're ordered now!
    

    This will look for each string in your query_string in each field in fields and OR the result

    I wish I still had my original source for this, but this is adapted from code I use.

    0 讨论(0)
提交回复
热议问题