djnago-filter用法
django-filter用法
集成drf
不指定字段的过滤参数,那么该字段就默认为exact,精准匹配
自定义filter文件内
from django_filters import rest_framework as rs_filters
from .models import *
class TestFilter(rs_filters.FilterSet):
title = rs_filters.CharFilter(lookup_expr='icontains') # 不指定field_name默认用变量名去对应字段
# title_name = rs_filters.CharFilter(lookup_expr='icontains', field_name='title')
max_price = rs_filters.NumberFilter(field_name='price', lookup_expr='lte')
min_price = rs_filters.NumberFilter(field_name='price', lookup_expr='gte')
class Meta:
model = Book
fields = ['title', 'price']
不必写max_price or min_price,只需要把price加进去就可以实现过滤
支持django的双下划线的跨表 eg:fields = ['publish__addr']
此外,字典可用于为每个字段指定多个查找表达式:
fields = {
'price': ['lt', 'gt'],
'release_date': ['exact', 'year__gt'],
}
在view.py内
from django_filters.rest_framework import DjangoFilterBackend
from .filter import TestFilter
class BookAPIView(ListAPIView):
queryset = Book.objects
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend] # 必须用加DjangoFilterBackend或其子类
filterset_class = TestFilter # 把自定义的过滤加上
过滤器和查找表达式不匹配(in、range、isnull)
直接将过滤器与其模型字段的类型匹配并不总是合适的,因为某些查找需要不同类型的值。in
这是、range
和isnull
查找的常见问题。我们来看看下面的产品型号:
class Product(models.Model):
category = models.ForeignKey(Category, null=True)
鉴于这category
是可选的,因此希望启用对未分类产品的搜索是合理的。以下是错误配置的 isnull
过滤器:
class ProductFilter(django_filters.FilterSet):
uncategorized = django_filters.NumberFilter(field_name='category', lookup_expr='isnull')
那么问题是什么?虽然基础列类型category
是整数,但isnull
查找需要一个布尔值。然而,ANumberFilter
只验证数字。过滤器不是“表达式感知”的,不会根据它们的lookup_expr
. 您应该使用与查找表达式的数据类型匹配的过滤器,而不是模型字段的数据类型。以下将正确地允许您搜索未分类的产品和一组类别的产品:
class NumberInFilter(django_filters.BaseInFilter, django_filters.NumberFilter):
pass
class ProductFilter(django_filters.FilterSet):
categories = NumberInFilter(field_name='category', lookup_expr='in')
uncategorized = django_filters.BooleanFilter(field_name='category', lookup_expr='isnull')
in
有关构建和range
csv过滤器的更多信息。
参数
禁用过滤器字段exclude
该exclude
选项接受要从自动过滤器生成中排除的字段名称黑名单。请注意,此选项不会禁用直接在FilterSet
.
class UserFilter(django_filters.FilterSet):
class Meta:
model = User
exclude = ['password'] # 把password排除
field_name
过滤的模型字段的名称。如果未提供此参数,则默认过滤器在FilterSet
类上的属性名称。字段名称可以通过使用 ORM 查找分隔符 ( __
) 连接相关部分来遍历关系。例如,产品的manufacturer__name
.
lookup_expr
应在过滤器调用中执行的字段查找.默认为 exact
. lookup_expr
如果表达式部分由 ORM 查找分隔符 ( ) 连接,则可以包含转换__
。例如,按年份部分过滤日期时间year__gt
。
method
一个可选参数,告诉过滤器如何处理查询集。它可以接受可调用对象或FilterSet
. 可调用对象接收一个QuerySet
、要过滤的模型字段的名称以及要过滤的值。它应该返回一个经过过滤的Queryset
.
请注意,该值由 验证Filter.field
,因此应该不需要原始值转换和空值检查。
class F(FilterSet):
"""Filter for Books by if books are published or not"""
published = BooleanFilter(field_name='published_on', method='filter_published')
def filter_published(self, queryset, name, value):
# construct the full lookup expression.
lookup = '__'.join([name, 'isnull'])
return queryset.filter(**{lookup: False})
# alternatively, you could opt to hardcode the lookup. e.g.,
# return queryset.filter(published_on__isnull=False)
class Meta:
model = Book
fields = ['published']
distinct
一个布尔值,指定过滤器是否将在查询集上使用 distinct。当使用跨越关系的过滤器时,此选项可用于消除重复结果。默认为False
.
exclude
一个布尔值,指定过滤器是否应该使用filter
或exclude
在查询集上。默认为False
.
required
一个布尔值,指定是否需要过滤器。默认为False
.
ChoiceFilter
此过滤器匹配其choices
参数中的值。当choices
在 上声明过滤器时,必须显式传递FilterSet
。例如,
class User(models.Model):
username = models.CharField(max_length=255)
first_name = SubCharField(max_length=100)
last_name = SubSubCharField(max_length=100)
status = models.IntegerField(choices=STATUS_CHOICES, default=0)
STATUS_CHOICES = (
(0, 'Regular'),
(1, 'Manager'),
(2, 'Admin'),
)
class F(FilterSet):
status = ChoiceFilter(choices=STATUS_CHOICES)
class Meta:
model = User
fields = ['status']
ChoiceFilter
还有一些参数可以选择不过滤,也可以选择按None
值过滤。每个参数都有一个对应的全局设置(设置参考)。
empty_label
:用于选择不过滤的显示标签。通过将此参数设置为 可以禁用该选择None
。默认为FILTERS_EMPTY_CHOICE_LABEL
.null_label
:用于选择按None
值过滤的显示标签。通过将此参数设置为 可以禁用该选择None
。默认为FILTERS_NULL_CHOICE_LABEL
.null_value
: 要匹配的特殊值以启用按None
值过滤。此值默认FILTERS_NULL_CHOICE_VALUE
为非空值(''
,None
,[]
,()
,{}
)。