Django REST framwork-07-过滤、搜索和排序

2024-03-23 20:20

本文主要是介绍Django REST framwork-07-过滤、搜索和排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、简介

REST框架的通用列表视图的默认行为是返回模型管理器的整个查询集。

筛选子类的任何视图的查询集的最简单方法是覆盖该GenericAPIView 的 .get_queryset() 方法。

基于 URL 传递的参数过滤

  1. URL
    考虑如下 URL 配置条目:
path('servers-base-url-args/<manufacturer>', views.ServersListView.as_view()),
  1. URL 请求
    http://www.qfsite.com/api/servers-base-url-args/del/
  2. 视图
    URL 传递的参数会在 self.kwargs 或者 self.args 中
class ServersListView(generics.ListAPIView):serializer_class = ServersSerializerdef get_queryset(self):"""默认返回所有的服务器,这里使用了过滤,只返回某一个厂商的。"""manufacturer = self.kwargs['manufacturer']return Servers.objects.filter(manufacturer=manufacturer)

基于 GET 方法中的参数过滤

  1. URL
    考虑如下 URL 配置条目:
path('servers-base-get-args/', ServersListView.as_view()),
  1. URL 请求
    http://www.qfsite.com/api/servers-base-get-args/?manufacturer=del
  2. 视图
    GET 方法传参是在 self.request.query_params 中,这是一个字典。
class ServersListView(generics.ListAPIView):serializer_class = ServersSerializerdef get_queryset(self):"""默认返回所有的服务器,这里使用了过滤,只返回某一个厂商的。"""queryset = Servers.objects.all()manufacturer = self.request.query_params.get('manufacturer', None)if manufacturer:queryset = queryset.filter(manufacturer=manufacturer)return queryset

通用过滤器(重点掌握)

REST框架还包括对通用过滤后端的支​​持,允许您轻松构建复杂的搜索和过滤器。

通用过滤器还可以在可浏览的API和管理API中将自身呈现为HTML控件。

在这里插入图片描述
在这里插入图片描述

配置过滤器后端 django-filters

DjangoFilterBackend
该 django-filter 库包含一个 DjangoFilterBackend 类,该类支持 REST 框架的高度可定制的字段过滤。

要使用 DjangoFilterBackend,请先安装 django-filter。然后添加 django_filters 到 Django的 INSTALLED_APPS

pip3 install django-filter
  1. 注册 APP
    在 settings.py 中设置
INSTALLED_APPS = [...'django_filters',
]

注意: 中间的是下划线 _

2.1 为全局设置
您现在应该将过滤器后端添加到您的设置:

在 settings.py 中设置

REST_FRAMEWORK = {'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

2.2 或者为具体某个视图设置
或者将过滤器后端添加到单个View或ViewSet。

view 或者 ViewSet 必须是基于 GenericAPIView 的类视图

from django_filters.rest_framework import DjangoFilterBackend
class UserListView(generics.ListAPIView):...filter_backends = [DjangoFilterBackend]
  1. 如何使用
    3.1 视图
    过滤字段的值必须是 等于的关系
    只需要在视图或视图集上设置 filterset_fields 属性,并列出要过滤的字段集
from django_filters.rest_framework import DjangoFilterBackendclass ServersListView(generics.ListAPIView):queryset = Servers.objects.all()serializer_class = ServersSerializerfilter_backends = [DjangoFilterBackend]filterset_fields = ['hostname', 'manufacturer']

3.2 URL 配置

urlpatterns = [path("servers-filter/", views.ServersFilterView.as_view()),
]

3.3 URL 请求
这将接受下面的请求:

http://www.qfedu.com/api/servers-filter/?hostname=db.server.yy.com&manufacturer=
3.4 效果图
填写过滤条件
在这里插入图片描述

过滤结果:
在这里插入图片描述

可以发现 django-filter 默认的过滤器支持的只是精确匹配。
假如希望进行模糊匹配,比如希望查找到所有包含 db.server 的主机名等。
这样的需求可以采用自定义过滤器的的方式。

自定义过滤类

利用 django-filter 自定义过滤类,对于更高级的过滤要求,您可以自己编写一个过滤器,这个过滤器很想 Django 中的 From 类 ,之后在指定视图中使用 filterset_class=自定义类名 来使用这个类。

1. 编写自定义过滤器的类

这个过滤器的目标是: 查找到创建时间在某个范围的服务器。

from django_filters import rest_framework as filters
from users.models import Serverclass ServersFilter(filters.FilterSet):"""服务器的过滤类"""# 可以自定义筛选器属性名,如 create_at_mincreate_at_min = filters.DateTimeFilter(field_name='create_at', lookup_expr='gte',label="创建时间 大于等于")create_at_max = filters.DateTimeFilter(field_name='create_at', lookup_expr='lte', label="创建时间 小于等于")class Meta:model = Serverfields = ['create_at_min', 'create_at_max']

核心参数

  • field_name: 筛选依据的模型字段的名称。如果未提供此参数,则会默认FilterSet类上的筛选器属性名称。字段名可以通过将相关部分与ORM查找分隔符(__)连接来遍历关系。例如 manufacturer__name
  • lookup_eper: 应在筛选器调用中执行的字段查找。默认为精确匹配。如果表达式部分由ORM查找分隔符(__)连接,则 lookup_expr 可以包含更多的查找转换规则。例如,通过日期时间的年部分 year__gt 来过滤日期时间。

label 属性的值会显示到页面提示上。

  1. 在视图中使用
from django_filters.rest_framework import DjangoFilterBackend
from .filters import ServersFilter
class ServersFilterViewSet(viewsets.ReadOnlyModelViewSet):queryset = Server.objects.all()serializer_class = ServerSerializerfilter_backends = [DjangoFilterBackend]filterset_class = ServersFilter
  1. URL 配置
    由于上面的视图是采用视图集(ViewSet)的方式,所以可以使用路由注册的方式。
router.register(r'servers-filter', views.ServersFilterViewSet)
  1. 效果图
    在这里插入图片描述

  2. 支持字段值的模糊匹配
    对主机名 hostname 进行模糊匹配,过滤器需进行如下配置
    模糊匹配相当于 MySql 中的 like.
    这里使用 icontains, i 是忽略大小写的。

class ServersFilter(filters.FilterSet):"""服务器的过滤类"""create_at = filters.DateFromToRangeFilter(label="创建时间范围搜索after-before")hostname = filters.CharFilter(field_name='hostname', lookup_expr='icontains')class Meta:model = Serverfields = ['create_at', 'hostname']

注意: Model 中的字段是 models.DateTimeField (年-月-日 时:分:秒).
在这里仍然可以使用 filters.DateFromToRangeFilter (年-月-日) 的方式进行过滤。

在这里插入图片描述

关键字参数 method

一个可选参数,告诉筛选器如何处理查询集。它可以接受FilterSet上的方法名称或者任意位置编写的函数。方法或函数接收一个QuerySet queryset、要筛选的模型字段的名称 name以及要筛选的值 value。它应该返回一个经过筛选的Queryset。

请注意,该值由Filter.field验证,因此不需要原始值转换和空值检查。

参考官方示例如下:

class F(FilterSet):"""根据图书是否已出版筛选图书"""published = BooleanFilter(field_name='published_on', method='filter_published')def filter_published(self, queryset, name, value):# 构造完整的查找表达式。lookup = '__'.join([name, 'isnull'])return queryset.filter(**{lookup: False})# 或者, 对于 lookup 你可以使用硬编码。 比如,# return queryset.filter(published_on__isnull=False)class Meta:model = Bookfields = ['published']# 也可以在类作用域之外定义一个函数
def filter_not_empty(queryset, name, value):lookup = '__'.join([name, 'isnull'])return queryset.filter(**{lookup: False})class F(FilterSet):"""根据图书是否已出版筛选图书"""published = BooleanFilter(field_name='published_on', method=filter_not_empty)class Meta:model = Bookfields = ['published']

更多
点我官方文档-过滤参考

支持跨表字段的匹配

如下示例中使用的 model:

class Servers(models.Model):"""服务器"""ENV = (("0", "测试"),("1", "生产"),("2", "开发"),("3", "预生产"),)project = models.ForeignKey("projects.Projects", related_name="servers", on_delete=models.CASCADE, verbose_name="所属项目", help_text="服务器属于哪个项目")env = models.CharField(max_length=1, choices= ENV,default="1", verbose_name="环境", help_text="哪个环境的服务器")host_name = models.CharField(max_length=128, unique=True, db_index=True, verbose_name="主机名", help_text="主机名")class Meta:"""元数据"""verbose_name = "服务器表"verbose_name_plural = verbose_nameclass Projects(models.Model):"""项目表"""name = models.CharField(max_length=30, verbose_name="项目名称", help_text="项目名称")class Meta:"""定义数据库中实际的表名称"""verbose_name = "项目表"verbose_name_plural = verbose_name

实现关系字段的过滤,可以使用下面的示例:

class ServersFilter(filters.FilterSet):"""服务器的过滤类"""project = filters.CharFilter(field_name='project__name', lookup_expr='icontains', label="所属项目")class Meta:model = Serversfields = ["env", "local_ip", "project"]

field_name 的值 project__name ,表示了关系字段的查询。
fields 中 project 是过滤器的属性名称,也是前端发送请求时候需要传递的 GET 请求参数名称。
lookup_expr 的 icontains 表示 包含的意思。
查询URL:
http://localhost:8000/servers/?project=项目名

SearchFilter 搜索

搜索使用的是 Django rest framework 自己的 SearchFilter

同样在浏览器 API 中会展现出一个搜索控件,可以方便前端人员、测试人员的测试。

视图

from rest_framework import filters
class ServersSearchViewSet(viewsets.ReadOnlyModelViewSet):queryset = Server.objects.all()serializer_class = ServerSerializerfilter_backends = [filters.SearchFilter]search_fields = ['hostname', 'manufacturer']

URL 配置

router.register(r'servers-search', views.ServersSearchViewSet)

在这里插入图片描述

可以支持基于双下划线的夸表搜索

search_fields = ['hostname', 'manufacturer', ' 'disk__capacity']

这样会增加搜索 硬盘容量在指定范围的 服务器
在这里插入图片描述

支持组合搜索
搜索主机名还有 db 字符并且硬盘容量是 200 的服务器

在这里插入图片描述

搜索的逻辑关系
默认搜索的条件是模糊匹配的,就是包含的意思。

还支持以下逻辑关系

  • '^' 匹配开头。
  • '=' 完全匹配。
  • '@' 全文搜索。(目前只支持Django的MySQL后端。)
  • '$' 正则表达式搜索。

示例

search_fields = ['$hostname']

在这里插入图片描述

OrderingFilter 排序

class ServersSearchViewSet(viewsets.ReadOnlyModelViewSet):queryset = Server.objects.all()serializer_class = ServerSerializerfilter_backends = [filters.SearchFilter, filters.OrderingFilter]search_fields = ['$hostname', 'manufacturer', 'disk__capacity']ordering_fields = ["create_at", "disk__capacity"]ordering = ["-create_at"]  # 默认排序字段

少张图

这篇关于Django REST framwork-07-过滤、搜索和排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/839427

相关文章

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

pandas数据过滤

Pandas 数据过滤方法 Pandas 提供了多种方法来过滤数据,可以根据不同的条件进行筛选。以下是一些常见的 Pandas 数据过滤方法,结合实例进行讲解,希望能帮你快速理解。 1. 基于条件筛选行 可以使用布尔索引来根据条件过滤行。 import pandas as pd# 创建示例数据data = {'Name': ['Alice', 'Bob', 'Charlie', 'Dav

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close