问题
I'm trying to create a django filter with multiple filter parameters (ex. name, age, height). However, I only want to filter by a parameter if it exists...
In my init:
def __init__(self, name=None, age=None, height=None):
self.name = name
self.age = age
self.height = height
in my query:
Person.objects.filter(name=self.name, age=self.age, height=self.height)
However, the problem is since the parameters are optional in the constructor, there is a chance that the filter is looking for None
values, which I don't want. If name='mike'
, age=25
, height=None
, I only want the filter to use the name
and age
parameters and exclude the height
. Something like:
Person.objects.filter(if self.name: name=self.name, if self.age: age=self.age, if self.height: height=self.height)
Is this possible? Or would I need to first check if every variable exists and have different cases for each possible filter query?
Thanks!
回答1:
from django.db import models as dmodels
filters = dmodels.Q(age=age) & dmodels.Q(name=name)
if height:
filters &= dmodels.Q(height=height)
Person.objects.filter(filters)
see here
回答2:
If you want to build a generic solution, use a Custom model manager
#manager.py
from django.db.models import Manager
class CustomManager(Manager):
def custom_filter(self, *args, **kwargs):
updated_kwargs = {k: v for k, v in kwargs.items() if v is not None}
return super().filter(*args, **updated_kwargs)
Attach this manager in your model class as,
#models.py
class Person(models.Model):
objects = CustomManager()
# other fields
Then, use this custom_filter(...)
method to query, similar to the built-in filter()
# example usage
Person.objects.custom_filter(name=self.name, age=self.age, height=self.height)
Note: This custom_filter
method will ommit all values that are None
来源:https://stackoverflow.com/questions/59413613/django-filter-query-if-filter-parameter-exists