Django系列之DRF搜索和过滤

1. model之间关系

python 复制代码
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)

2. DRF搜索

在DRF中使用搜索功能,只需要在 viewsets 视图类中定义 filter_backendssearch_fields 即可使用。

filter_backends:后端使用的搜索和过滤类。
search_fields :要执行搜索条件的字段,搜索为模糊查询(要在哪些字段上执行模糊查询,支持多表连表查询)。

对应的URL格式就是这种:http://127.0.0.1:9000/test/publishes/?search=北京

python 复制代码
class PublishModelViewSets(viewsets.ModelViewSet):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer
    filter_backends = (SearchFilter, )
    search_fields = ("name", "city", "book__title")   

3. django-filter简单过滤

安装包: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中添加:

python 复制代码
INSTALLED_APPS = [
	...
    'django_filters'
]
python 复制代码
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=甘肃

python 复制代码
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']           # 完全相等
    }
    

4. django-filter自定义过滤器类和过滤器函数

  • 过滤器中常用的字段类型,这些类型要和模型中对应的字段类型兼容:

    CharFilter 字符串类型
    BooleanFilter 布尔类型
    DateTimeFilter 日期时间类型
    DateFilter 日期类型
    DateRangeFilter 日期范围
    TimeFilter 时间类型
    NumberFilter 数值类型,对应模型中IntegerField, FloatField, DecimalField

  • 字段内参数说明:

    field_name:过滤字段名,对应模型中的字段名
    lookup_expr:查询时所要进行的操作,和ORM中运算符一致
    method:该字段对应的自定义过滤器函数

  • Meta字段使用:

    model:引用的模型,不是字符串
    fields:指明过滤字段,可以是列表,列表中字典可以过滤,默认是判断相等;也可以是字典,字典可以自定义操作。
    exclude:排除字段,不允许使用列表中字典进行过滤

5. django-filter 使用示例

在视图类中添加自定义的过滤类:

python 复制代码
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 筛选关键字。

python 复制代码
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。

相关推荐
普普通通的南瓜19 分钟前
IP证书在关键信息基础设施安全防护中的实践与挑战
网络·数据库·网络协议·tcp/ip·安全·ssl
合作小小程序员小小店30 分钟前
桌面开发,超市管理系统开发,基于C#,winform,sql server数据库
开发语言·数据库·sql·microsoft·sqlserver·c#
quweiie37 分钟前
thinkphp8.0链接SQL SERVER2022数据库
数据库·sqlserver·thinkphp
Databend1 小时前
如何打造AI时代的数据基石 | Databend Meetup 上海站
数据库
老华带你飞2 小时前
海产品销售系统|海鲜商城购物|基于SprinBoot+vue的海鲜商城系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·海鲜商城购物系统
合作小小程序员小小店2 小时前
桌面开发,在线%超市销售管理%系统,基于vs2022,c#,winform,sql server数据
开发语言·数据库·microsoft·c#
SelectDB2 小时前
字节跳动:Apache Doris + AI 一站式融合数据引擎的探索与实践
数据库·apache
a***13143 小时前
vscode配置django环境并创建django项目(全图文操作)
vscode·django·sqlite
IvorySQL3 小时前
PostgreSQL 18 - 时间约束 (Temporal Constraints)
数据库·postgresql·开源
q***61413 小时前
从MySQL迁移到PostgreSQL的完整指南
数据库·mysql·postgresql