如何将过滤后端应用于Django Rest Framework中所有资源的所有字段?

时间:2014-11-30 16:33:47

标签: django django-rest-framework

我有很多资源,我想将DjangoFilterBackend应用于所有这些资源。

尝试settings.py

中的设置
'DEFAULT_FILTER_BACKENDS': [
            'rest_framework.filters.DjangoFilterBackend',
        ]

但它不起作用

我尝试只将filter_backends = (filters.DjangoFilterBackend,)添加到我的某个资源中,但仍然无效。

只有在我明确添加filter_fields = ('col1','col2',)之后,它才开始使用这些字段。

有什么办法可以将过滤后端应用到所有资源和所有字段(例如我使用权限的方式......)?

感谢。

3 个答案:

答案 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_classfilter_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__