Query when parameter is none django

前端 未结 5 1327
春和景丽
春和景丽 2020-12-31 09:50

I want to make a query, something like

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

... but there are some cases when for example y

相关标签:
5条回答
  • 2020-12-31 09:54

    You can write:

    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)
    
    0 讨论(0)
  • 2020-12-31 09:58

    You can create a model manager and then assign it to your model so that you can use this manager to any model. This solution is more 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()
    

    Assign this manager to your model:

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

    And in your view you can use the above manager as:

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

    Now you don't have to worry about the none values. Hope this helps.

    0 讨论(0)
  • 2020-12-31 10:10

    I do not know, if I get your question, but

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

    gives you the queryset, where the ycolumn is non-null (IS NOT NULL).

    Here's the relevant documentation.

    EDIT: Check if y is None and build your queryset dynamically:

    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)
    ...
    

    If there are too many arguments to deal with, you could use something like this; assuming that x, y, z are stored in a dictionary 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)
    
    0 讨论(0)
  • 2020-12-31 10:10

    A better approach on the otherwise very readable @rolling-stone answer:

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

    Anyway, depending on the specific filter, you'll need to apply filters together in the same .filter() call, so the "blind" way only works in the simple cases. See https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships for more information on those cases.

    0 讨论(0)
  • 2020-12-31 10:18

    Something like this could work:

    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)
    

    Because QuerySets are lazy, this doesn't involve any database activity.

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