在 filters.py 中,我定义了一个 CustomFilter
,它的值类型为 ComboSortFilter
和 IntegerListFilter
。
在 views.py 中,我定义了一个具有 filter_class = CustomFilter
的 ViewSet,这对于 GET
请求非常有效,在 url 中使用查询字符串参数,得到使用自定义过滤进行处理。
我还需要支持 POST
请求,因为有些过滤条件太长,无法放入 URL。
所以我在我的 ViewSet 中添加了一个 post
方法,我从 request.DATA
中提取参数,然后对它们进行过滤、序列化和分页……
在 views.py 中我的 ViewSet 的 post 方法中:
queryset = MyModel.objects.filter(**filter_args)
page = self.paginate_queryset(queryset)
serializer = self.get_pagination_serializer(page)
return Response(serializer.data)
对于简单的过滤,上面的工作正常。但是,我在 CustomFilter
中定义的使用 ComboSortFilter
和 IntegerListFilter
过滤字段的过滤有点复杂:
在 filters.py 中:
class IntegerListFilter(django_filters.Filter):
def filter(self, qs, value):
if value not in (None, ''):
integers = [int(v) for v in value.split(',')]
return qs.filter(**{'{0}__{1}'.format(self.name, self.lookup_type): integers})
return qs
class ComboSortFilter(django_filters.Filter):
def __init__(self, threshold, lookup_type, order='ASC'):
super(ComboSortFilter, self).__init__(lookup_type=lookup_type)
self.threshold = threshold
self.order = order
def filter(self, qs, value):
if value not in (None, ''):
fields = [str(v) for v in value.split(',')]
for field in fields: # filters each field's values relative to threshold
qs = qs.filter(**{'{0}__{1}'.format(field, self.lookup_type): self.threshold})
if self.order == 'DESC':
fields = ['-{0}'.format(f) for f in fields]
qs = qs.order_by(*fields)
return qs
class CustomFilter(django_filters.FilterSet):
thing_ids = IntegerListFilter(name="thing_id", lookup_type='in')
sort_desc = ComboSortFilter(lookup_type='gte', threshold=100, order='DESC')
sort_asc = ComboSortFilter(lookup_type='lte', threshold=100)
有什么方法可以从 ViewSet 的 post 方法中引用 CustomFilter
FilterSet 或我的两个自定义过滤器中的任何一个?我不想在 views.py
中复制所有这些过滤代码来让它工作。
Django-rest-framework:filters 上的所有文档只包括简单的例子,要么在 View 中滚动你自己的,要么使用过滤器类。有没有一种方法可以直接从 View 中调用过滤器类,覆盖它通常从查询字符串中获取的值?
最佳答案
想通了:
class MyPostViewSet(BaseModelViewSet):
def post(self, request, *args, **kwargs):
queryset = self.queryset
filter_params = request.DATA or request.GET
if filter_params:
queryfilter = self.filter_class(filter_params, queryset=queryset)
queryset = queryfilter.qs
page = self.paginate_queryset(queryset)
serializer = self.get_pagination_serializer(page)
return Response(serializer.data)
关于python - 用于 POST 请求的 Django 休息框架自定义过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27133032/