在Django/DRF项目中如何为视图追加过滤器后端且遵循DRY原则?
在DRF中保留默认过滤器并追加额外过滤器的方案
你可以通过以下几种方式实现无需重复默认过滤器、自动继承settings配置的需求,完全符合DRY原则:
方法1:重写视图的get_filter_backends方法
DRF的视图类提供了get_filter_backends方法用于获取最终生效的过滤器列表,你可以在目标视图中重写这个方法,将默认过滤器与额外过滤器合并:
from rest_framework import viewsets class FooViewSet(viewsets.ModelViewSet): # 仅定义需要追加的额外过滤器 extra_filter_backends = [AdditionalFilter] def get_filter_backends(self): # 先获取默认的过滤器列表(自动继承settings中的DEFAULT_FILTER_BACKENDS) default_backends = super().get_filter_backends() # 合并默认过滤器与额外过滤器 return default_backends + self.extra_filter_backends
这种方式直接在单个视图中修改,适合零散的视图需求。
方法2:封装自定义基类视图
如果你的项目中有大量视图需要追加额外过滤器,推荐封装一个基类视图,将合并逻辑统一实现,其他视图只需继承该基类并定义额外过滤器即可:
from rest_framework import viewsets class BaseModelViewSet(viewsets.ModelViewSet): # 默认空列表,子类可覆盖添加额外过滤器 extra_filter_backends = [] def get_filter_backends(self): return super().get_filter_backends() + self.extra_filter_backends # 子类视图只需继承基类并指定额外过滤器 class FooViewSet(BaseModelViewSet): extra_filter_backends = [AdditionalFilter] class BarViewSet(BaseModelViewSet): extra_filter_backends = [AnotherFilter]
这种方式统一管理逻辑,后续settings中的默认过滤器变更时,所有继承该基类的视图都会自动同步,无需逐个修改。
方法3:使用装饰器动态追加
如果你不想修改基类,也可以用装饰器为视图动态追加过滤器:
def add_filter_backends(*extra_backends): def decorator(view_class): original_get_backends = view_class.get_filter_backends def new_get_backends(self): default_backends = original_get_backends(self) return default_backends + list(extra_backends) view_class.get_filter_backends = new_get_backends return view_class return decorator # 使用装饰器为视图添加额外过滤器 @add_filter_backends(AdditionalFilter) class FooViewSet(viewsets.ModelViewSet): pass
注意事项
- 过滤器的执行顺序由列表顺序决定,如果你需要额外过滤器优先执行,可以调整拼接顺序(例如
return self.extra_filter_backends + super().get_filter_backends())。 super().get_filter_backends()会自动处理父类视图中定义的filter_backends属性,同时优先继承settings中的默认配置,逻辑更灵活可靠。
内容的提问来源于stack exchange,提问作者cezar
相关产品推荐
相关产品推荐

