Я использую фильтры drf и django, чтобы выполнить некоторую фильтрацию моих данных.Для фильтрующего бэкэнда я использую django_filters.rest_framework.DjangoFilterBackend
.
class ProductsViewSet(LoginRequiredMixin, ModelViewSet):
authentication_classes = (authentication.SessionAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,
rest_framework.filters.SearchFilter,
rest_framework.filters.OrderingFilter,)
filter_class = ProductFilter
search_fields = ("title", "description", "company", "country", "status",)
ordering_fields = ("title", "description", "company", "country", "status",)
Мой класс_фильтра:
class ProductFilter(filters.FilterSet):
price_from = filters.NumberFilter(field_name="price", lookup_expr="gte",
label="Min price",
min_value=0)
price_to = filters.NumberFilter(field_name="price", lookup_expr="lte",
label="Max price",
min_value=0)
# MultipleChoiceFilters
country = filters.MultipleChoiceFilter(field_name="country", choices=COUNTRY_CHOICES)
company = filters.MultipleChoiceFilter(field_name="company", choices=COMPANY_CHOICES)
status = filters.MultipleChoiceFilter(field_name="status", choices=STATUS_CHOICES)
class Meta:
model = Product
fields = ["price_from", "price_to", "country",
"company", "status"]
@property
def qs(self):
parent = super(ProductFilter, self).qs
return parent.order_by("-timestamp")
def __init__(self, *args, **kwargs):
super(ProductFilter, self).__init__(*args, **kwargs)
user = self.request.user
user_products = Product.objects.filter(user=user)
# Initial Data #############################################################
price_min = user_products.all().aggregate(Min("price"))["price__min"]
price_max = user_products.all().aggregate(Max("price"))["price__max"]
self.filters["price_from"].extra["initial"] = price_min
self.filters["price_to"].extra["initial"] = price_max
COUNTRY_CHOICES = tuple(Product.objects.filter(user=user).values_list("country", "country__name").distinct().order_by("country__name"))
self.filters["country"].extra['choices'] = COUNTRY_CHOICES
COMPANY_CHOICES = tuple(Product.objects.filter(user=user).values_list("company", "company").distinct().order_by("company"))
self.filters["company"].extra['choices'] = COMPANY_CHOICES
Моя проблема заключается в том, что если я пытаюсь фильтровать по нескольким значениям, а одно из них не существуетЯ не получаю никаких результатов.
Например, если я хочу фильтровать по полевой компании, которая является ForeignKey, используя 2 значения:
компания Google с идентификатором= 2 не существует ни в одном из моих объектов, и
компания Microsoft с идентификатором = 3, который существует,
вернет следующеенет результатов
api/products?company=2&company=3
То же самое происходит, если поле просто CharField.Кроме того, такое же поведение возникает при использовании filter_fields и filter_class.
Сначала я реализовал свою собственную настройку фильтрации get_queryset
, но подумал, что я мог бы сделать вещи менее сложными, используя бэкэнд фильтра.
Я не уверен, почему это происходит, если существуют два значения, с которыми я фильтрую, все работает нормально.