安装配置
基本概念
filterset:
filterset类.过滤集.在meta类中要指定一个model.和fields.model类的fields字段中的属性会被添加到过滤条件中.同时可以定义此类的类属性,类属性均为额外过滤字段.类属性过滤字段,无需再meta中的feilds中声明即可添加过滤.这点与serializer并不相同.
filter:
filter.过滤器.针对某一个字段来详细定义过滤的情况.值的预处理,单字段过滤逻辑均在此类中.fitler的实例通常被用作filterset类的类属性.
安装命令
pip install django-filter
配置文件
在settings.py中安装并配置django_filters应用:
INSTALLED_APPS = [
...
'django_filters',
]
REST_FRAMEWORK = {
...
# 过滤器默认后端,通常还会加上ordering和search组成三兄弟
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter',
],
}
使用流程
示例准备
模型
class Project(models.Model):
name = models.CharField(max_length=200,verbose_name='项目名')
start_date = models.DateField(blank=True, null=True,verbose_name='开始日期')
stars = models.IntegerField(null=True,blank=True,verbose_name="星星")
spm = models.ForeignKeyField('User', blank=True, null=True,verbose_name='负责人')
class Meta:
verbose_name = "项目"
class User(models.Model):
username = models.CharField(max_length=200,verbose_name='用户名')
class Meta:
verbose_name = "用户"
序列化器
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = "__all__"
视图
class ProjectViewSet(ViewSets.ModelViewSet):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
自定义过滤器
按照<项目名><等于>过滤
过滤器类
import django_filters as filters
from .models import Project
class ProjectFilter(filters.FilterSet):
class Meta:
model = Project # 模型名
fields = ['name',]
更新视图
class ProjectViewSet(ViewSets.ModelViewSet):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
filterset_class = BookFilter # 过滤类
前端传参
const name = 'prj1'
axios.get(url,{params:{name}})
捷径
在使用默认参数的时候(字段名等于某值)的时候,视图中可以如此简写
class ProjectViewSet(ViewSets.ModelViewSet):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
filterset_fields = ['name'] # 不指定过滤类而直接指定过滤字段,与过滤类中meta类中的fields的值写法相同.
更多过滤条件(大于/小于等)
过滤器类
class ProjectFilter(filters.FilterSet):
class Meta:
model = Project # 模型名
fields = {"stars":["lte","gte"]}
前端传参
const stars__lte = 13
axios.get(url,{params:{stars__lte}})
这样就可以获得星星数小于13的所有项目了.
此时fields的值从列表/元组变为了字典, 字典中的键必须是model的合法属性名, 每个键的值是django支持的lookup中的一员, 前端传参的时候用双下划线链接字段与lookup即可正确使用.同样的,捷径中也支持这种字典的写法.
附录:lookup的全集
自定义前端传参的字段名
很多时候我们不希望暴露双下划綫语法,或者希望能获得一个更加可读的query参数,此时可以使用自定义字段来完成.
过滤器类
class ProjectFilter(filters.FilterSet):
min_stars = filters.NumberFilter(field_name="stars", lookup_expr='gte')
class Meta:
model = Project # 模型名
fields = ('min_stars',)
前端传参
const min_stars = '13'
axios.get(url,{params:{min_stars}})
这样min_stars就替代了stars__gte作为传参的键了.
自定义过滤方法
过滤器类
class ProjectFilter(filters.FilterSet):
mine = filters.CharFilter(method='filter_mine') # 传入了method函数后,过滤器不再校验字段是否存在于模型上
class Meta:
model = Project # 模型名
fields = ('mine',)
def filter_mine(self, queryset, name, value):
#函数名必须和上面定义的字符串相同,接受4个参数,request是当前请求,queryset是当前查询集,name是当前字段名,value是当前字段值.此函数返回值必须是一个queryset.
return queryset.filter(Q(collectors=self.request.user)).distinct()
内置filter
CharFilter UUIDFilter BooleanFilter ChoiceFilter TypedChoiceFilter MultipleChoiceFilter TypedMultipleChoiceFilter DateFilter TimeFilter DateTimeFilter IsoDateTimeFilter DurationFilter ModelChoiceFilter ModelMultipleChoiceFilter NumberFilter NumericRangeFilter RangeFilter DateRangeFilter DateFromToRangeFilter DateTimeFromToRangeFilter IsoDateTimeFromToRangeFilter TimeRangeFilter AllValuesFilter AllValuesMultipleFilter LookupChoiceFilter
这些filter大部分都是在做字段值的预处理(类型转化/校验).比较重要的参数有
field_name
- 需要被过滤的模型字段,也就是你model字段指向的模型类的一个字段属性(例如上文的name,或者stars).
如果这个参数没有被指定,会选取过滤器在filterset类中的属性名作为默认值
class ProjectFilter(filters.FilterSet):
stars = filters.NumberFilter()
class Meta:
model = Project # 模型名
fields = ('stars',)
# 此时直接传stars就是按照星星数准确过滤了,如果写成star并且Project模型中找不到这个名字,会报错
这个字段支持关系分隔符
__
例如:Project的manufacturer__name
lookup_expr
查询的lookup.默认值是
exact
.同样支持__
语法.比如一个datetime类型字段的year_lt
内置常用过滤器行为描述
1.CharFilter
字符串过滤器,没啥好说的.注意当你把一个原本是BooleanField的字段设置为CharFilter的时候,它的值只能是1或者0才能被正确过滤.
2.BooleanFilter
布尔过滤器,
(True, 'True', 'true', '1')
这些值是true,(False, 'False', 'false', '0')
这些值是false,其他所有值都是None.当值为None时,不执行过滤.3.ChoiceFilter
选项过滤器.仍然需要使用choice的值而不是key.但是会根据choices的参数做校验,从而返回一个not valid choice的异常.如果针对一个choice的字段使用了charfilter.那么传入非法选项的时候.如果类型也相同,会返回空值,否则一般会有类型转换错误.使用必要不是很强烈.
4.MultipleChoiceFilter
多选过滤器
多选字段的传参: 在query中使用同一个键名传入多个参数. 例如/plantest/plan_tasks/?page=1&page_size=3&result_status=1&result_status=2
这样就可以同时过滤即等于1又等于2的值了.
5.ModelChoiceFilter
模型类过滤器.根据外键值来过滤.非法值同样会抛出not valid choice.但是需要传入queryset参数.可以通过此参数来限制备选的值(例如分配任务时排除管理员.)
6.ModelMultipleChoiceFilter
模型类多选过滤.没啥好说的.