【问题标题】:Query when parameter is none django参数为无时查询 django
【发布时间】:2011-10-23 19:50:04
【问题描述】:

我想查询,比如

Model.objects.filter(x=x).filter(y=y).filter(z=z) 

...但在某些情况下,例如 y 为无。这实际上是在数据库中搜索 y 列中的空值——如果没有,是否有一种巧妙的方法可以基本上忽略该查询参数,即返回查询集

Model.objects.filter(x=x).filter(z=z)?

【问题讨论】:

    标签: python mysql django django-models


    【解决方案1】:

    我不知道,如果我得到你的问题,但是

    Model.objects.filter(x=x, y__isnull = False, z=z)
    

    为您提供查询集,其中 ycolumn 为非空 (IS NOT NULL)。

    Here's相关文档。

    编辑:检查 y 是否为 None 并动态构建您的查询集:

    if y is None:
        qs = Model.objects.filter(x=x).filter(z=z)
    elif z is None:
        qs = Model.objects.filter(x=x).filter(y=y)
    ...
    

    如果要处理的参数太多,你可以使用这样的东西;假设xyz 存储在字典中your values

    your_values = { 'x' : 'x value', 'y' : 'y value', 'z' : 'value'}
    arguments = {}
    for k, v in your_values.items():
        if v:
            arguments[k] = v
    
    Model.objects.filter(**arguments)
    

    【讨论】:

    • 稍微编辑了我的问题,但不,这不是我的问题。如果我发布 x 和 z,但不发布 y,那么我希望能够找到所有包含 x 和 z 的元素,无论它们是否包含 y。就目前而言,它假设 y 为 None,并提取所有 x、z 和 y=None 的元素。
    • 现在我明白了你想要达到的目标。请看我的回答。
    • 这给我留下了 8 种可能的组合来检查... :(
    • 我已经编辑了我的帖子,以反映您的评论。它现在应该适合你了:-)
    【解决方案2】:

    这样的事情可能会奏效:

    models = Model.objects.all()
    
    variables = {'x':'x','y':'y','z':'z'}
    
    for key, value in variables.items():
        if key=='x' and value:
            models = models.filter(x=value)
        if key=='y' and value:
            models = models.filter(y=value)
        if key=='z' and value:
            models = models.filter(z=value)
    

    因为QuerySets are lazy,这不涉及任何数据库活动。

    【讨论】:

    • 这是否意味着我只是将所有 100 亿个对象(请原谅夸大其词)加载到内存中?
    • 不,因为 QuerySet 是惰性的(请参阅我的答案中发布的链接。)基本上models = Model.objects.all() 不会将任何内容加载到内存中,任何过滤器也不会加载,直到您实际评估 QuerySet。来自文档:You can stack filters together all day long, and Django won't actually run the query until the QuerySet is evaluated.
    • 阅读该链接(惰性查询集)后,我认为答案是否定的。我对自己的反应太迟了。太棒了,谢谢。
    • 这是完美的。再次感谢。
    • oneliner: Model.objects.filter(**dict([(k, v) for k, v in variables.iteritems() if v]))
    【解决方案3】:

    对于原本非常可读的@rolling-stone 答案的更好方法:

    models = Model.objects.all()
    
    variables = {'x':x,'y':y,'z':z}
    
    for key, value in variables.items():
        if value is not None:
            models = models.filter(**{key: value})
    

    无论如何,根据特定的过滤器,您需要在同一个 .filter() 调用中一起应用过滤器,因此“盲目”方式仅适用于简单的情况。有关这些案例的更多信息,请参阅https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

    【讨论】:

    • 确实,这很好。谢谢。
    【解决方案4】:

    您可以创建一个模型管理器,然后将其分配给您的模型,以便您可以将此管理器用于任何模型。这个解决方案更 Pythonic。

    class GridManager(models.Manager):
    
        def applyFilters(self, *args, **kwargs):
             new_kwargs = {}
             for eachKey in kwargs:
                 val = kwargs[eachKey]
                 if val != '' and val != None:
                     new_kwargs[eachKey] = val
             if new_kwargs:
                 return super(GridManager, self).get_query_set().filter(*args, **new_kwargs)
             else:
                 return super(GridManager, self).get_query_set()
    

    将此经理分配给您的模型:

    class some_model(models.Model):
         your fields.....
         ......
         objects = models.Manager()
         grid_manager = GridManager()
    

    在您看来,您可以将上述管理器用作:

    objects = some_model.grid_manager.applyFilters(x=value, y = value, z = None)
    

    现在您不必担心 none 值。希望这会有所帮助。

    【讨论】:

    • 这很有趣,我得试试这个。谢谢。
    【解决方案5】:

    你可以写:

    filters = {'x':'abc', 'y':None, 'z':2}
    # here we filter out the None values of the dict 
    filters = dict(filter(lambda (k, v): v is not None, filters.items()))
    
    # We use the dict to create the query
    qs = Model.objects.filter(**filters)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 2014-10-13
      • 2020-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多