Django REST Framework 实现数据查找、过滤与排序详解
本文通过CMDB物理服务器管理实例,详细演示如何在Django REST Framework中实现高效的数据列表展示。内容涵盖Model定义、Serializer序列化配置以及ViewSet视图集开发,重点讲解如何利用django-filter实现多条件过滤、关键字搜索及自定义排序功能,为前端提供完整的列表查询接口支持。
在各类管理系统中,列表数据的展示是核心功能之一。为了提升用户体验,系统通常需要对列表数据进行查找、过滤和排序等操作,而这些逻辑大多在后台服务中执行。Django REST Framework(DRF)提供了强大的工具链,能够轻松实现上述数据操作。下文将通过具体案例进行详细说明。
示例代码已托管至 GitHub:https://github.com/jinjidejuren/drf_learn
以CMDB(配置管理数据库)系统为例,作为资产管理的核心组件,它需要支持对服务器数据进行精确过滤和查找,以便快速获取用户期望的资产信息。
实现Model定义
在本示例项目中,首要任务是对物理服务器进行条件过滤。物理服务器的数据模型定义在 apps/assets/models.py 文件中,具体字段结构如下:
class Server(models.Model):
"""
物理服务器
"""
status_choice = (
('online', '上线'),
('offline', '下线'),
('normal', '正常'),
('abnormal', '异常')
)
server_name = models.CharField(verbose_name=u'服务器名称', max_length=128, blank=False, null=False)
server_num = models.CharField(verbose_name=u'服务器编号', max_length=128, blank=True, null=True)
brand = models.CharField(verbose_name=u'品牌', max_length=64, blank=True, null=True)
model = models.CharField(verbose_name=u'型号', max_length=64, blank=True, null=True)
cpus = models.IntegerField(verbose_name=u'cpu核数', default=0)
ram = models.IntegerField(verbose_name=u'内存大小', default=0)
disk = models.IntegerField(verbose_name=u'磁盘大小', default=0)
product_date = models.DateTimeField(verbose_name=u'生产日期', auto_now_add=True)
status = models.CharField(verbose_name=u'状态', max_length=16, choices=status_choice)
created_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True)
modified_time = models.DateTimeField(verbose_name=u'修改时间', auto_now_add=True)
class Meta:
verbose_name = u'服务器'
verbose_name_plural = verbose_name
def __str__(self):
return self.server_name
实现Serializer序列化器
接下来,需要为 Server 模型编写对应的序列化类,代码位于 apps/assets/serializers.py 文件中:
class ServiceSerializer(serializers.ModelSerializer):
"""
服务器序列化
"""
class Meta:
model = Server
fields = ('id', 'server_name', 'server_num', 'brand', 'model', 'cpus',
'ram', 'disk', 'product_date', 'status', 'created_time',
'modified_time')
在定义 fields 时,可以使用 __all__ 表示包含模型中的所有字段。此外,序列化器还可以指定模型字段之外的其他信息,例如嵌套对象或自定义字段,具体设计需依据实际业务逻辑而定。
实现ModelViewSet视图集
ModelViewSet 允许我们围绕用户请求对数据进行增、删、改、查等处理。在此部分,我们需要实现 ServerViewSet 类:
class ServerViewSet(viewsets.ModelViewSet):
"""
物理服务器视图
"""
queryset = Server.objects.all().order_by('-created_time')
serializer_class = ServerSerializer
pagination_class = MyFormatResultsSetPagination
queryset 属性指定了返回列表的数据源,这里返回所有信息并按创建时间逆序排列,确保最新数据优先展示,这更符合用户的操作习惯。
serializer_class 属性定义了返回数据的序列化格式,此处指定为 ServerSerializer 所定义的 fields 内容。
pagination_class 属性指定了分页策略,这里使用了自定义的分页类 MyFormatResultsSetPagination。
实现Router路由配置
若用户希望访问服务器信息,需配置对应的路由。这与之前介绍的路由配置方式类似,需要创建一个 router 对象,并将 server 的路由注册进去。
from rest_framework import routers router = routers.DefaultRouter() router.register(r'servers', views.ServerViewSet, base_name='servers') urlpatterns = [ url(r'^', include(router.urls)) ]
所有对 servers 资源的访问请求均由 ServerViewSet 进行处理。
尝试访问接口
访问地址 http://127.0.0.1:8060/assets/v1/servers/,返回信息如下:

注意:在后续测试前,需先添加示例数据。
按条件获取数据
在实际操作中,用户往往需要获取符合特定条件的数据。例如,对于物理服务器,可能需要指定品牌、CPU核数或内存大小,甚至要求按CPU核数排序。这些需求需要对 ServerViewSet 进行进一步扩展。
若需实现条件过滤,首先需安装 django-filter 模块:
pip install django-filter
在配置文件 settings/base.py 中添加 django_filters 应用:
INSTALLED_APPS = [ # 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'django_filters', 'apps.assets', 'apps.rbac' ]
在 apps/assets/views.py 文件顶部引入以下包:
from django_filters.rest_framework import DjangoFilterBackend from rest_framework import filters from django_filters import rest_framework
ServerViewSet 可添加相应的过滤配置:
class ServerViewSet(viewsets.ModelViewSet):
"""
物理服务器视图
"""
queryset = Server.objects.all()
serializer_class = ServerSerializer
pagination_class = MyFormatResultsSetPagination
filter_backends = (rest_framework.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter, )
filter_class = ServerFilter
search_fields = ('server_name', '=brand', 'status', )
ordering_fields = ('cpus', 'ram', 'disk', 'product_date', )
ordering = ('-created_time', )
filter_backends 指定了过滤器的类型,此处设置了 DjangoFilterBackend(用于过滤)、SearchFilter(用于搜索)和 OrderingFilter(用于排序)。
1. 过滤功能
过滤功能配置了过滤类为 ServerFilter,该类的定义位于 apps/assets/filters.py 文件中:
import django_filters
from .models import *
class ServerFilter(django_filters.rest_framework.FilterSet):
"""
物理服务器过滤器
"""
server_name = django_filters.CharFilter(name='server_name', lookup_expr='icontains')
brand = django_filters.CharFilter(name='brand', lookup_expr='icontains')
cpus = django_filters.NumberFilter(name='cpus')
ram = django_filters.NumberFilter(name='ram')
disk = django_filters.NumberFilter(name='disk')
class Meta:
model = Server
fields = ['server_name', 'brand', 'cpus', 'ram', 'disk', ]
这意味着可以通过 'server_name'、'brand'、'cpus'、'ram'、'disk' 等字段对物理服务器信息进行过滤,从而获取相应的序列化列表。
例如,获取 CPU 为 24 核的物理服务器:

返回的服务器列表中,所有服务器的 CPU 核数均为 24:
GET https://www.ipython.cn/assets/v1/servers/?server_name=&brand=&cpus=24&ram=&disk=
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"results": [
{
"id": 9,
"server_name": "data-server2",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 2500,
"product_date": "2018-06-23T13:51:09.641473Z",
"status": "online",
"created_time": "2018-06-23T13:51:09.642583Z",
"modified_time": "2018-06-23T13:51:09.642764Z"
},
{
"id": 8,
"server_name": "data-server2",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 5000,
"product_date": "2018-06-23T13:51:02.466031Z",
"status": "online",
"created_time": "2018-06-23T13:51:02.467274Z",
"modified_time": "2018-06-23T13:51:02.467471Z"
},
{
"id": 7,
"server_name": "data-server1",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 5000,
"product_date": "2018-06-23T13:50:55.622403Z",
"status": "offline",
"created_time": "2018-06-23T13:50:55.623315Z",
"modified_time": "2018-06-23T13:50:55.623431Z"
},
{
"id": 6,
"server_name": "data-server",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 5000,
"product_date": "2018-06-23T13:50:48.088028Z",
"status": "online",
"created_time": "2018-06-23T13:50:48.089433Z",
"modified_time": "2018-06-23T13:50:48.089703Z"
},
{
"id": 5,
"server_name": "harbor-server3",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:49:27.590015Z",
"status": "offline",
"created_time": "2018-06-23T13:49:27.590980Z",
"modified_time": "2018-06-23T13:49:27.591097Z"
},
{
"id": 4,
"server_name": "harbor-server3",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:49:23.783337Z",
"status": "abnormal",
"created_time": "2018-06-23T13:49:23.784243Z",
"modified_time": "2018-06-23T13:49:23.784500Z"
},
{
"id": 3,
"server_name": "harbor-server2",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:49:16.348672Z",
"status": "online",
"created_time": "2018-06-23T13:49:16.349555Z",
"modified_time": "2018-06-23T13:49:16.349663Z"
},
{
"id": 2,
"server_name": "harbor-server1",
"server_num": "server-02-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:48:57.853354Z",
"status": "online",
"created_time": "2018-06-23T13:48:57.853990Z",
"modified_time": "2018-06-23T13:48:57.854098Z"
},
{
"id": 1,
"server_name": "harbor-server",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:48:48.777153Z",
"status": "online",
"created_time": "2018-06-23T13:48:48.778048Z",
"modified_time": "2018-06-23T13:48:48.778166Z"
}
],
"pagination": 9,
"page_size": 10,
"page": 1
}
2. 搜索功能
搜索功能需指定 search 关键字以查询特定信息。例如,搜索名称以 'test' 开头的服务器:
http://127.0.0.1:8060/assets/v1/servers/?search=test
获取到的列表如下:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"results": [
{
"id": 14,
"server_name": "test-server1",
"server_num": "server-01-shanghai",
"brand": "dell",
"model": "Modular",
"cpus": 32,
"ram": 256,
"disk": 500,
"product_date": "2018-06-23T13:52:40.583743Z",
"status": "offline",
"created_time": "2018-06-23T13:52:40.584409Z",
"modified_time": "2018-06-23T13:52:40.584512Z"
},
{
"id": 13,
"server_name": "test-server",
"server_num": "server-01-shanghai",
"brand": "dell",
"model": "Modular",
"cpus": 32,
"ram": 256,
"disk": 2500,
"product_date": "2018-06-23T13:52:24.760819Z",
"status": "normal",
"created_time": "2018-06-23T13:52:24.761475Z",
"modified_time": "2018-06-23T13:52:24.761578Z"
}
],
"pagination": 2,
"page_size": 10,
"page": 1
}
在 search_fields 中可以指定多种查找模式:
'^name' 表示以 name 字段开头匹配
'=name' 表示精确匹配
'@' 表示全局检索(仅 MySQL 数据源支持)
'$' 表示正则匹配
对应的 search_fields 示例如下:
search_fields = ('^server_name', '=brand', 'status', )
3. 排序功能
在 ordering 字段中指定了默认排序方式(按创建时间逆序):
ordering = ('-created_time', )
也可通过以下方式指定排序:
queryset = Server.objects.all().order_by('-created_time')
若需自定义排序字段,需指定 ordering 字段的内容:
例如,按内存大小对服务器进行排序:
http://127.0.0.1:8060/assets/v1/servers/?ordering=ram
获取的信息列表如下:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"results": [
{
"id": 6,
"server_name": "data-server",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 5000,
"product_date": "2018-06-23T13:50:48.088028Z",
"status": "online",
"created_time": "2018-06-23T13:50:48.089433Z",
"modified_time": "2018-06-23T13:50:48.089703Z"
},
{
"id": 7,
"server_name": "data-server1",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 5000,
"product_date": "2018-06-23T13:50:55.622403Z",
"status": "offline",
"created_time": "2018-06-23T13:50:55.623315Z",
"modified_time": "2018-06-23T13:50:55.623431Z"
},
{
"id": 8,
"server_name": "data-server2",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 5000,
"product_date": "2018-06-23T13:51:02.466031Z",
"status": "online",
"created_time": "2018-06-23T13:51:02.467274Z",
"modified_time": "2018-06-23T13:51:02.467471Z"
},
{
"id": 9,
"server_name": "data-server2",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 24,
"ram": 64,
"disk": 2500,
"product_date": "2018-06-23T13:51:09.641473Z",
"status": "online",
"created_time": "2018-06-23T13:51:09.642583Z",
"modified_time": "2018-06-23T13:51:09.642764Z"
},
{
"id": 1,
"server_name": "harbor-server",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:48:48.777153Z",
"status": "online",
"created_time": "2018-06-23T13:48:48.778048Z",
"modified_time": "2018-06-23T13:48:48.778166Z"
},
{
"id": 2,
"server_name": "harbor-server1",
"server_num": "server-02-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:48:57.853354Z",
"status": "online",
"created_time": "2018-06-23T13:48:57.853990Z",
"modified_time": "2018-06-23T13:48:57.854098Z"
},
{
"id": 3,
"server_name": "harbor-server2",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:49:16.348672Z",
"status": "online",
"created_time": "2018-06-23T13:49:16.349555Z",
"modified_time": "2018-06-23T13:49:16.349663Z"
},
{
"id": 4,
"server_name": "harbor-server3",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:49:23.783337Z",
"status": "abnormal",
"created_time": "2018-06-23T13:49:23.784243Z",
"modified_time": "2018-06-23T13:49:23.784500Z"
},
{
"id": 5,
"server_name": "harbor-server3",
"server_num": "server-01-beijing",
"brand": "dell",
"model": "Rack",
"cpus": 24,
"ram": 128,
"disk": 5000,
"product_date": "2018-06-23T13:49:27.590015Z",
"status": "offline",
"created_time": "2018-06-23T13:49:27.590980Z",
"modified_time": "2018-06-23T13:49:27.591097Z"
},
{
"id": 10,
"server_name": "data-server2",
"server_num": "server-01-shanghai",
"brand": "hp",
"model": "HPE Apollo 4200 Gen9",
"cpus": 32,
"ram": 256,
"disk": 2500,
"product_date": "2018-06-23T13:51:30.706187Z",
"status": "online",
"created_time": "2018-06-23T13:51:30.707754Z",
"modified_time": "2018-06-23T13:51:30.707878Z"
}
],
"pagination": 14,
"page_size": 10,
"page": 1
}
上述排序、过滤等操作可组合使用,通常为前端列表搜索查询提供接口支持。
小结
本章介绍了 Django REST Framework 中 Model 的定义、序列化、增删改查以及搜索、排序等功能,这是开发后端接口必须掌握的核心技巧。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









