我有很多资源,我想将DjangoFilterBackend应用于所有这些资源。
尝试settings.py
'DEFAULT_FILTER_BACKENDS': [
'rest_framework.filters.DjangoFilterBackend',
]
但它不起作用
我尝试只将filter_backends = (filters.DjangoFilterBackend,)
添加到我的某个资源中,但仍然无效。
只有在我明确添加filter_fields = ('col1','col2',)
之后,它才开始使用这些字段。
有什么办法可以将过滤后端应用到所有资源和所有字段(例如我使用权限的方式......)?
感谢。
答案 0 :(得分:10)
现在您要告诉Django REST Framework将DjangoFilterBackend
用于所有视图,但您没有告诉它应该如何生成FilterSet
。
fields
are set to None
, django-filter
会自动为模型上的所有字段生成FilterSet
。如果filter_fields
are not set to None
,Django REST Framework将自动生成FilterSet
,这意味着您无法使用默认的DjangoFilterBackend
。
您可以创建自定义DjangoFilterBackend
,这会自动为模型上的所有字段生成FilterSet
。
from rest_framework.filters import DjangoFilterBackend
class AllDjangoFilterBackend(DjangoFilterBackend):
"""
A filter backend that uses django-filter.
"""
def get_filter_class(self, view, queryset=None):
"""
Return the django-filters `FilterSet` used to filter the queryset.
"""
filter_class = getattr(view, 'filter_class', None)
filter_fields = getattr(view, 'filter_fields', None)
if filter_class or filter_fields:
return super(AllDjangoFilterBackend, self).get_filter_class(self, view, queryset)
class AutoFilterSet(self.default_filter_set):
class Meta:
model = queryset.model
fields = None
return AutoFilterSet
对于视图定义自定义filter_class
或filter_fields
的情况,这仍将使用原始过滤器后端,但它会为所有其他情况生成自定义FilterSet
。请注意,您不应该允许过滤未通过API返回的字段,因为您要面对未来的安全问题(例如通过密码过滤用户列表的用户)。
答案 1 :(得分:1)
凯文·布朗(Kevin Browns)的回答很棒,但是现在可能有点过时了。
使用django-filter == 2.1.0运行AllDjangoFilterBackend
过滤器后端会引发以下情况:
Setting 'Meta.model' without either 'Meta.fields' or 'Meta.exclude' has been deprecated since 0.15.0 and is now disallowed. Add an explicit 'Meta.fields' or 'Meta.exclude' to the AutoFilterSet class.
用fields = None
替换exclude = ''
似乎足以使用所有字段。完整代码如下:
from django_filters.rest_framework import DjangoFilterBackend
class AllDjangoFilterBackend(DjangoFilterBackend):
'''
Filters DRF views by any of the objects properties.
'''
def get_filter_class(self, view, queryset=None):
'''
Return the django-filters `FilterSet` used to filter the queryset.
'''
filter_class = getattr(view, 'filter_class', None)
filter_fields = getattr(view, 'filter_fields', None)
if filter_class or filter_fields:
return super().get_filter_class(self, view, queryset)
class AutoFilterSet(self.default_filter_set):
class Meta:
exclude = ''
model = queryset.model
return AutoFilterSet
将其保存到your_project / your_app / filters.py(或类似文件),然后确保您的设置文件包含:
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'your_project.your_app.filters.AllDjangoFilterBackend'
),
}
答案 2 :(得分:0)
好吧,我知道已经很久了,但是今天(2019/11)我才刚遇到这个问题,所以我决定以这种方式分享我认为更好的东西:
只需将__all__
用于过滤字段
filter_fields = __all__