Django3 模糊查询/filters.SearchFilter的使用,基于viewsets.ModelViewSet

背景描述

模型

from django.db import models

from interfaces.validate import validate_include
from testcases.models import Testcases
from utils.base_models import BaseModel
from utils.pure_validator import JSONValidator


class Interfaces(BaseModel):
    id = models.AutoField(verbose_name='id主键', primary_key=True, help_text='id主键')
    name = models.CharField('接口名称', max_length=200, unique=True, blank=False, null=False, help_text='接口名称')
    project = models.CharField('接口Path', max_length=200, unique=True, help_text='接口Path')

    project = models.ForeignKey('projects.Projects', on_delete=models.PROTECT,
                                related_name='interfaces', help_text='所属项目')
    env = models.ForeignKey('envs.Envs', on_delete=models.PROTECT, null=True, blank=True,
                            related_name='env', help_text='对应的环境变量', default=None)
    project_module = models.ForeignKey('project_module.ProjectModule', on_delete=models.PROTECT,
                                       related_name='interfaces', help_text='接口所属模块',
                                       null=True, blank=True, default=None)

    tester = models.CharField('测试人员', max_length=50, help_text='测试人员')
    desc = models.TextField('描述', max_length=200, null=True, blank=True, help_text='备注信息')
    # 请求类型,请求参数(Params Body Header Cookie Auth 设置),请求示例,响应示例,状态码,备注,状态,自定义字段
    REQUEST_TYPE_CHOICES = (
        ('GET', 'GET'),
        ('POST', 'POST'),
        ('PUT', 'PUT'),
        ('DELETE', 'DELETE'),
        ('PATCH', 'PATCH')
    )
    method = models.CharField('请求类型', max_length=10, choices=REQUEST_TYPE_CHOICES, default='get',
                              help_text='请求类型')
    # 请求参数
    params = models.JSONField('请求参数', null=True, blank=True, help_text='请求参数', validators=[JSONValidator()])
    json = models.JSONField('请求体', null=True, blank=True, help_text='请求Body', validators=[JSONValidator()])
    data = models.JSONField('请求表单', null=True, blank=True, help_text='请求表单', validators=[JSONValidator()])

    headers = models.JSONField('请求Header', null=True, blank=True, help_text='请求Header',
                               validators=[JSONValidator()])
    cookies = models.JSONField('请求Cookie', null=True, blank=True, help_text='请求Cookie',
                               validators=[JSONValidator()])
    auth = models.CharField('请求Auth', max_length=100, null=True, blank=True, help_text='请求Auth')
    response_example = models.TextField('响应示例', null=True, blank=True, help_text='响应示例')
    response_status_code = models.CharField('状态码', max_length=10, null=True, blank=True, help_text='状态码')
    STATUS_CHOICES = (
        ('published', '已发布'),
        ('testing', '测试中'),
        ('deprecated', '已废弃'),
        ('developing', '开发中')
    )
    status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='published')
    include = models.JSONField('接口前置信息', help_text='接口前置信息', validators=[validate_include])

    class Meta:
        db_table = 'tb_interfaces'
        verbose_name = '接口信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

视图

import logging
from datetime import datetime

from rest_framework import filters
from rest_framework import permissions
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

from interfaces.models import Interfaces
from project_module.models import ProjectModule
from testcases.models import Testcases
from utils.json_utils import json_utils
from .serializers import InterfacesModelSerializer, TestcasesInterfacesModelSerializer, \
    ConfiguresInterfacesModelSerializer, InterfacesRunSerializer

logger = logging.getLogger('Django')


class InterfacesViewSet(viewsets.ModelViewSet):
    """
    list:
    获取接口列表数据

    retrieve:
    获取接口详情数据

    update:
    更新接口信息

    names:
    获取接口名称

    sava_case:
    保存接口为用例

    """
    queryset = Interfaces.objects.all()
    serializer_class = InterfacesModelSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['=name', '=id', '=tester']
    # search_fields = ['name', 'id', 'tester']
    ordering_fields = ['id', 'name', 'tester']

    permission_classes = [permissions.IsAuthenticated]

Search实现的全量查询

首先我们在视图中,规定了查询字段。

queryset = Interfaces.objects.all()
serializer_class = InterfacesModelSerializer

# 指定筛选和排序后端
filter_backends = [filters.SearchFilter, filters.OrderingFilter]

# 定义搜索字段,'=' 表示精确匹配
search_fields = ['=name', '=id', '=tester']

如果你想改成模糊查询,你可以将 search_fields 的设置改为:

search_fields = ['name', 'id', 'tester']

代码语法

search_fields​ 属性在 Django REST framework 中用于指定哪些字段应该被 SearchFilter​ 后端用于搜索查询。以下是各种前缀和后缀的详细解释:

  1. ‘^’:此前缀表示字段应以搜索项开头。例如,如果你有一个名为 ‘name’ 的字段,并且设置为 '^name'​,那么搜索字符串 ‘abc’ 将匹配任何名称以 ‘abc’ 开头的项目。
  2. ‘=’:此前缀表示字段应完全匹配搜索项。例如,如你有一个名为 ‘name’ 的字段,并且设置为 '=name'​,那么搜索字符串 ‘abc’ 将只匹配名称完全等于 ‘abc’ 的项目。
  3. ‘@’:此前缀仅适用于文本字段。它表示字段应与搜索项进行全文搜索(仅适用于支持全文搜索的数据库)。
  4. $​:此前缀表示字段应完全匹配搜索项。例如,如你有一个名为 ‘name’ 的字段,并且设置为 'name$'​,那么搜索字符串 ‘abc’ 将只匹配名称以 ‘abc’ 结尾的项目。

如果不使用任何符号,将默认进行包含(即模糊)匹配。例如,如果你设置为 'name'​,那么搜索字符串 ‘abc’ 将匹配任何名称中包含 ‘abc’ 的项。

注意:这些都是基于 ORM 查询用语实现的,由于 ORM 查询用语依赖于数据库引擎,所以在某些数据库中可能无法工作。

/swagger/json/

image

精确匹配

image

由于之前配置了name​为查询字段,则输入对应的值,可以如图精准查询到值。

反向示例

若输入部分则无法查询到

image

由于之前没有配置desc​,所以没法查询到对应的值

image

此处为反向示例,下面的内容由于篇幅原因不在一一赘述。

部分匹配

    # 精准匹配
    # search_fields = ['=name', '=id', '=tester']
    # 部分匹配
    search_fields = ['name', '=id', '^desc']
  1. 'name'​:这个设置表示在 name​ 字段上执行包含搜索。也就是说,如果你所提供的搜索字词出现在 name​ 字段中的任何位置,该项都会被返回。例如,如果搜索 ‘abc’,将会返回所有 name​ 字段中包含 ‘abc’ 的项目。

    name

    image

  2. '=id'​:这里的等号前缀表示只有当 id​ 字段的值和搜寻字词完全匹配时才返回结果。例如,如果搜索词为 ‘123’,那么仅当 id​ 字段完全等于 ‘123’ 的项目才会被返回。

    id

    image

  3. '^desc'​:这个设置意味着搜索将匹配以搜索字词开头的 desc​ 字段。例如,如果搜索 ‘intro’,那么所有 desc​ 字段以 ‘intro’ 开头的项目都会被返回。

    desc

    image

匹配以xxx结尾,作者模拟出现一些问题。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Franciz小测测

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值