过滤从简单到更复杂的示例
普通香草过滤
要筛选任何视图,请覆盖其 get_queryset
方法以返回筛选的查询集
class HREmployees(generics.ListAPIView):
def get_queryset(self):
return Employee.objects.filter(department="Human Resources")
然后,所有 API 函数将使用筛选的查询集进行操作。例如,上述视图的列表将仅包含其部门为人力资源的员工。
访问 get_queryset 中的查询参数
基于请求参数的过滤很容易。
self.request
,self.args
和 self.kwargs
可用,并指向当前请求及其过滤参数
def DepartmentEmployees(generics.ListAPIView):
def get_queryset(self):
return Employee.objects.filter(department=self.kwargs["department"])
让 API 参数决定要过滤的内容
如果你想要更多的灵活性并允许 API 调用传入参数来过滤视图,你可以插入过滤后端,如 Django Request Framework(通过 pip 安装)
from rest_framework import filters
class Employees(generics.ListAPIView):
queryset=Employee.objects.all()
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ("department", "role",)
现在,你可以进行 API 调用/api/employees?department=Human Resources
,你将获得仅属于人力资源部门的员工列表,或者仅获取人力资源部门的经理。
你可以将查询集筛选与 Django Filter Backend 结合使用,没有问题。过滤器将对 get_queryset
返回的过滤查询集起作用
from rest_framework import filters
class HREmployees(generics.ListAPIView):
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ("department", "role",)
def get_queryset(self):
return Employee.objects.filter(department="Human Resources")
FilterSets
到目前为止,你可以在上述情况下使用简单类型匹配。
但是,如果你想要一些更复杂的东西,比如年龄在 25 到 32 岁之间的人力资源员工名单呢?
问题的答案:过滤器
过滤器集是定义如何过滤模型的各个字段的类。
像这样定义 em
class EmployeeFilter(django_filters.rest_framework.FilterSet):
min_age = filters.django_filters.NumberFilter(name="age", lookup_expr='gte')
max_age = filters.django_filters.NumberFilter(name="price", lookup_expr='lte')
class Meta:
model = Employee
fields = ['age', 'department']
name
指向要过滤的字段
lookup_expr
基本上是指你在过滤查询集时使用的相同名称,例如你可以使用 lookup_expr="startswith"
进行开始匹配,这相当于 Employee.objects.filter(department__startswith="Human")
然后使用 filter_class
而不是 filter_fields
在视图类中使用它们
class Employees(generics.ListAPIView):
queryset=Employee.objects.all()
filter_backends = (filters.DjangoFilterBackend,)
filter_class = EmployeeFilter
现在你可以做/api/employees?department=Human Resources&min_age=25&max_age=32
不完全匹配和关系
过滤器类和表达式与你在查询集中指定过滤的方式非常相似
你可以使用“__”表示法来过滤关系中的字段,例如,如果部门是员工的外键,则可以添加
filter_fields=("department__name",)
然后你可以做/api/employees?department__name=Human Resources
或者更优雅的是,你可以创建一个过滤器集,添加一个名为 dept
的过滤器变量并将其名称设置为 department__name
,允许你进行/api/employees?dept=Human Resources