Always True Q object

廉价感情. 提交于 2019-12-10 02:31:56

问题


I want to create some part of Django ORM filter query dinamicly, now I can do:

if some:
   Obj.filter(
       some_f1=some_v1,
       f1=v1,
       f2=v2,
       f3=v3,
       f4=v4,
       ...
   )
else:
   Obj.filter(
       f1=v1,
       f2=v2,
       f3=v3,
       f4=v4,
       ...
   )

I want something without code duplicate like this:

Obj.filter(
    Q(some_f1=some_v1) if some else True,  # what to use instead of True?
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)

回答1:


Here's a hacky way to get an always true Q object:

always_true = ~Q(pk=None)

This depends on the fact that the primary key cannot be null.




回答2:


Try this;

conditions = {'f1':f1,'f2':f2, 'f3':f3}
if some:
    conditions['some_f1'] = some_v1

Obj.objects.filter(**conditions)



回答3:


as Alasdair answered in comment:

Obj.filter(
    Q(some_f1=some_v1) if some else Q(), 
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)



回答4:


Based on this answer we can make conditional argument passing

Obj.filter(
    *( (Q(some_f1=some_v1),) if some  else ()),    
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)

So, if some is True we add tuple (Q(some_f1=some_v1),) to arguments list, in other case we add empty tuple (), also we need to wrap it in *(), as always when we passing tuple of non-keyword args




回答5:


Since QuerySets are lazy, you can create the default filter, and then add others base on your conditions. Django won't run the query until the QuerySet is evaluated (for example, iterating through it in a for loop)

filtered_objects = Obj.filter(
    some_f1=some_v1,
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)
if some:
    filtered_objects.filter(some_f1=some_v1)



回答6:


An "always true" Q object is equivalent to No Q object when using AND (basic filter syntax; i.e. x and True == x), thus a DRYer alternative for your use case is as follows:

filters = dict(f1=v1,
               f2=v2,
               f3=v3,
               f4=v4,
               ...)
if some:
    filters['some_f1'] = some_v1

qs = obj.filter(**filters)

Modify according to your needs.



来源:https://stackoverflow.com/questions/33517468/always-true-q-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!