class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=8)
email = models.CharField(max_length=32)
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
pub_date = models.DateField()
publish = models.ForeignKey(Publish, on_delete=models.CASCADE, null=True)
在DRF中使用搜索功能,只需要在 viewsets 视图类中定义 filter_backends
和 search_fields
即可使用。
filter_backends
:后端使用的搜索和过滤类。
search_fields
:要执行搜索条件的字段,搜索为模糊查询(要在哪些字段上执行模糊查询,支持多表连表查询)。
对应的URL格式就是这种:http://127.0.0.1:9000/test/publishes/?search=北京
。
class PublishModelViewSets(viewsets.ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_backends = (SearchFilter, )
search_fields = ("name", "city", "book__title")
安装包:pip install django-filter
使用:在 viewsets 视图类的 filter_backends
属性中追加 DjangoFilterBackend
,再添加 filterset_fields
属性即可使用。
filterset_fields
:要执行过滤条件的字段,执行的是精准查询。
对应的URL格式就是这种 http://127.0.0.1:9000/test/publishes/?name=GansuEngEduPublisher&city=甘肃
:
在settings配置文件的app中添加:
INSTALLED_APPS = [
...
'django_filters'
]
class PublishModelViewSets(viewsets.ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_backends = (SearchFilter, DjangoFilterBackend)
search_fields = ("name", "city", "book__title") # 模糊查询
filterset_fields = ("name", "city") # 精准查询
filterset_fields
也可以按照自定义的方式过滤。
对应的URL格式就是这种:http://127.0.0.1:9000/test/publishes/?name__icontains=gansueng&city=甘肃
class PublishModelViewSets(viewsets.ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_backends = (SearchFilter, DjangoFilterBackend)
search_fields = ("name", "city", "book__title") # 模糊查询
filterset_fields = {
"name": ["icontains"], # 包含此查询条件,大小写不敏感
"city": ['exact'] # 完全相等
}
CharFilter 字符串类型
BooleanFilter 布尔类型
DateTimeFilter 日期时间类型
DateFilter 日期类型
DateRangeFilter 日期范围
TimeFilter 时间类型
NumberFilter 数值类型,对应模型中IntegerField, FloatField, DecimalField
field_name:过滤字段名,对应模型中的字段名
lookup_expr:查询时所要进行的操作,和ORM中运算符一致
method:该字段对应的自定义过滤器函数
model:引用的模型,不是字符串
fields:指明过滤字段,可以是列表,列表中字典可以过滤,默认是判断相等;也可以是字典,字典可以自定义操作。
exclude:排除字段,不允许使用列表中字典进行过滤
在视图类中添加自定义的过滤类:
class PublishModelViewSets(viewsets.ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_backends = (SearchFilter, DjangoFilterBackend)
search_fields = ("name", "city", "book__title")
filter_class = PublishFilter # 自定义过滤类
在app中新建一个filters.py文件,编写自己的自定义过滤函数,也可以不写,使用默认的 orm 筛选关键字。
from django_filters import filters, FilterSet
from app01.models import Publish
class PublishFilter(FilterSet):
pub_city = filters.CharFilter(field_name='city', lookup_expr='exact')
pub_email = filters.CharFilter(field_name='email', method='filter_email')
@staticmethod
def filter_email(queryset, field_name, value):
"""
出版社邮件以前端传过来的value值结尾的出版社
:param queryset: 查询到的数据集
:param field_name: 过滤的字段名
:param value: 前端传过来的值
:return: 过滤后的数据集
"""
print(field_name, value)
return queryset.filter(**{f"{field_name}__endswith": value})
class Meta:
model = Publish # 模型名
fields = ["pub_city", "pub_email"] # 过滤字段
对应的URL格式就是这样:http://127.0.0.1:9000/test/publishes/?pub_city=北京&pub_email=edu
。
注意:上述的自定义过滤器类和过滤器函数的方式,在 django-filter
的某些版本不适用,会导致无法过滤,获取到的是全集。上述使用的 django-filter
版本为 21.1。