" Django-filter " Возможно ли использовать FilterClass(FilterSet) MultipleChoiceFilter внутри методов ViewSet? Django 1.11, Python 2.7
У меня есть мой класс ClassFilter(FilterSet)
с некоторыми Filters fx. MultipleChoiceFilter
, ModelMultipleChoiceFilter
и т.д. в нем:
class ClassFilter(FilterSet):
something_severity = MultipleChoiceFilter(choices=Something.SEVERITY_CHOICES, method='something_severity_filter', widget=CSVWidget)
def something_severity_filter(self, queryset, name, severities):
if severities:
queryset = queryset.filter(something_state=Something.STATE_SOMETHING)
...
return queryset
class Meta:
model = Something
fields = []
Он отлично работает, когда дело доходит до фильтрации конечных точек. Он присваивается классу следующим образом:
class ClassViewSet(mixins....., DefaultApiViewSet):
filter_class = ClassFilter
, имея filter_class = ClassFilter
. Все работает просто отлично, но теперь я сомневаюсь, могу ли я использовать ClassFilter
MultipleChoiceFilter
внутри ClassViewSet
методов.
Это означает, что выполняя POST
метод в ClassViewSet
, я хочу получить MultipleChoiceFilter
из FilterClass
для фильтрации моего метода, получив его как SomethingFilter.get_filters()
метод
@action(detail=False, methods=['post'])
def something_update(self, req):
...
all_filters = SomethingFilter.get_filters()
for serializer_filter in serializer_filters:
for filter in all_filters:
if(serializer_filter == filter):
f = all_filters[filter]
Теперь f
- это фильтр, который мне нужен, так что это MultipleChoiceFilter
. Но когда я пытаюсь фильтровать с помощью этого фильтра, он выдает ошибку.
f.filter(queryset, [('LOW')]) #filter the queryset with the filter based on LOW choice
Броски:
assertionError: Filter 'something_severity' must have a parent FilterSet to find '.something_severity_filter()'
В документации для django-filter
это именно строка: https://github.com/carltongibson/django-filter/blob/f4866a9852d569861651cc733f909fe0e378131b/django_filters/filters.py#L823
Итак, я хочу сказать, если есть способ действительно фильтровать такой метод с помощью ClassFilter
как у меня. Если есть какой-то другой способ, как на самом деле сделать это правильно. Я уверен, что есть, так что в конечном итоге мне не придется делать другую фильтрацию и сохранять низкую связь.
Если есть что-то, что не ясно сказано, позвольте мне добавить к этому вопросу! Большое спасибо за любую помощь.
Так что я вернулся к проблеме и придумал решение.
Когда вы установили некоторые нужные вам фильтры в классе FilterSet(MultipleChoiceFilter,...)
class CarFilter(FilterSet):
wheel = MultipleChoiceFilter(choices=Wheel.CHOICES, method='wheel_filter', widget=CSVWidget)
def wheel_filter(self, queryset, name, cars):
if cars:
...
return queryset
class Meta:
model = Car
fields = []
Вам необходимо реализовать класс filter в ViewSet:
class CarViewSet(DefaultApiViewSet):
queryset = Car.objects.all()
serializer_class = CarSerializer
filter_class = CarFilter
Вы можете использоватьфильтр по своему усмотрению в методах ViewSet, если зададите его следующим образом:
ВАЖНО! - При использовании widget=CSVWidget
в MultipleChoiceFilter выше, это работает следующим образом:
def car_method(self, req):
queryset = self.filter_queryset(self.get_queryset())
self.filter_class({"wheel": "MEDIUM,LOW"}, queryset).qs
Когда мы НЕ используем widget=CSVWidget
, это работает следующим образом:
def car_method(self, req):
queryset = self.filter_queryset(self.get_queryset())
self.filter_class({'alert_severity': ['MEDIUM', 'LOW'], 'update_state': ['is_updated']}}, queryset).qs
Закончено! Мы отфильтровали автомобили на основе их колес.