06. Django REST framework - 过滤、排序、异常处理、自动生成接口文档
1 过滤针对于 list,获取所有(对于列表数据可能需要根据字段进行过滤) 2 在请求路径中带过滤条件,对查询结果进行过滤

# models.py 表模型 from django.db import models class Book(models.Model): name = models.CharField(max_length=34) price = models.IntegerField() # serializer.py 序列化器 from app01 import models from rest_framework import serializers class BookModelSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" # urls.py 路由 from django.contrib import admin from django.urls import path,include from rest_framework.routers import SimpleRouter from app01 import views router = SimpleRouter() router.register('book',views.BookView) urlpatterns = [ path('admin/', admin.site.urls), path('',include(router.urls)), ] 演示准备
内置过滤类的使用
1 在视图类views.py中(必须继承GenericAPIView) from app01 import models from app01 import serializer from rest_framework.viewsets import ModelViewSet from rest_framework.filters import SearchFilter # 导入内置过滤类 class BookView(ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializer.BookModelSerializer # 配置过滤类(局部使用) filter_backends = [SearchFilter,] # 配置过滤字段 search_fields = ['name','price'] 2 浏览的地址: # 查询的时候,所有条件都给search,并支持模糊匹配,search可以是name字段,也可以是price http://127.0.0.1:8000/book/?search=红精灵 http://127.0.0.1:8000/book/?search=11 3 全局使用:在settings.py配置文件中配置 REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.SearchFilter',) }
第三方过滤类使用(django-filter)
内置的SearchFilter过滤类,功能一般,如果你想实现更高级的过滤,自己写,使用第三方
我们可以通过添加django-fitlter扩展来增强支持。
1 安装(django:2.2, 3.1, 3.2) pip3 install django-filter
Django提示找不到模板django_filters/rest_framework/form.html
此处原因是忘记在INSTALLED_APPS
当中注册app 'django_filters'
。
只需要在settings.py
的INSTALLED_APPS
当中加入'django_filters'
即可。
INSTALLED_APPS = [
'django_filters'
]
2 在视图类views.py中(必须继承GenericAPIView)添加filter_fields属性,指定可以过滤的字段 from app01 import models from app01 import serializer from rest_framework.viewsets import ModelViewSet from django_filters.rest_framework import DjangoFilterBackend # 导入第三方过滤类 class BookView(ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializer.BookModelSerializer # 使用第三方 # 配置过滤类(局部使用) filter_backends=[DjangoFilterBackend,] # 配置过滤字段 filter_fields=['name','price'] 3 浏览的地址: # 查询可以通过字段查询,但不支持模糊查询 http://127.0.0.1:8000/book/?price=11&name=红精灵 http://127.0.0.1:8000/book/?price=11 4 全局使用:在settings.py配置文件中配置 REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) } # 局部使用(在视图类中加)
自己定义过滤类
1 写一个类,继承第三方过滤类(最好自定义一个py文件,auth.py) from rest_framework.filters import BaseFilterBackend class Myfilter(BaseFilterBackend): def filter_queryset(self, request, queryset, view): name = request.GET.get('name') queryset = queryset.filter(name__contains=name) return queryset 2 在视图类views.py中配置 from app01 import models from app01 import serializer from rest_framework.viewsets import ModelViewSet from app01.auth import Myfilter # 导入自定义过滤类 class BookView(ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializer.BookModelSerializer ## 自己定义的 filter_backends = [Myfilter, ] 3 浏览的地址:支持模糊查询 http://127.0.0.1:8000/book/?name=精
总结
1 APIViwe中有哪些类属性 renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES parser_classes = api_settings.DEFAULT_PARSER_CLASSES authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES 2 GenericAPIView中有哪些类属性 filter_backends = api_settings.DEFAULT_FILTER_BACKENDS pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
排序
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置filter_backends(排序本身也是过滤),使用rest_framework.filters.OrderingFilter
过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
1 在views.py 视图类中 from app01 import models from app01 import serializer from rest_framework.viewsets import ModelViewSet from rest_framework.filters import OrderingFilter # 导入过滤器排序类 class BookView(ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializer.BookModelSerializer ###排序 # 配置排序类(局部使用) filter_backends = [OrderingFilter, ] # 配置排序字段 ordering_fields=['price','name'] 2 请求方式:(postman中测试) http://127.0.0.1:8000/book/?ordering=price # 默认升序 http://127.0.0.1:8000/book/?ordering=-price # 降序 http://127.0.0.1:8000/book/?ordering=-price,-name # 配多个按,分隔 3 全局使用:在settings.py 配置文件中配置 REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.OrderingFilter',), }
异常处理 Exceptions
REST framework提供了异常处理,我们可以自定义异常处理函数,不论正常还是异常,通过定制,我们可以返回我们想要返回的样子
步骤
- 自定义函数
- 在配置文件中配置函数
注意
如果没有配置自己处理异常的规则,会执行默认的,如下:
from rest_framework import settings
from rest_framework.views import exception_handler
默认配置流程怎么走?
# 1、 APIView源码
# dispatch方法源码
except Exception as exc:
response = self.handle_exception(exc)
# handle_exception方法源码
response = exception_handler(exc, context)
# 2、views种的exception_handler方法
def exception_handler(exc, context):
···
# 3、 默认配置文件
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
# 在views.py 视图类中写一个带错误的视图类 from rest_framework.views import APIView class TestView(APIView): throttle_classes = [MyThrottling, ] def get(self, request): a=[1,3,4] # 4/0 print(a[100]) return Response('test') # urls.py 路由 from django.urls import path from app01 import views urlpatterns = [ path('test/', views.TestView.as_view()), ]
REST framework提供了异常处理,我们可以自定义异常处理函数。
1 手动创建一个名为exception的py文件,名字随意,在文件中写一个函数 from rest_framework.views import exception_handler from rest_framework.response import Response def custom_exception_handler(exc, context): # 先调用REST framework默认的异常处理方法获得标准错误响应对象 response=exception_handler(exc, context) # 捕获异常后端窗口信息打印 print(response) # 只要出错,这个就是None print(exc) # 错误信息在exc里 print(context.get('view')) # 视图类 print(context.get('request').get_full_path()) # 当次请求的request对象 # 在此处补充自定义的异常处理 if not response: # 更细粒度的对异常做一个区分 if isinstance(exc,IndexError): response=Response({'status':5001,'msg':'越界异常'}) elif isinstance(exc,ZeroDivisionError): response = Response({'status': 5002, 'msg': '越界异常'}) else: response= Response({'status': 5000, 'msg': '没有权限'}) # 在这可以记录日志:一旦出错就记录日志 return response 2 在settings.py 配置文件中配置 REST_FRAMEWORK = { 'EXCEPTION_HANDLER':'app01.excepiton.custom_exception_handler', }
3 以后只要视图中执行出了错误,就会捕获异常,记录日志,并返回统一的格式给前端
或者:
源码exception_handler方法有两种情况,if判断第一种情况是处理了APIException对象的异常返回Reponse对象,第二种情况是处理了其他异常返回了None,这里我们针对这两种情况的异常进行定制处理
- exc:错误原因
- context:字典,包含了当前请求对象和视图类对象
自定义异常处理方法
from rest_framework.views import exception_handler
from rest_framework.response import Response
def myexception_handler(exc, context):
# 先执行原来的exception_handler帮助我们处理
res = exception_handler(exc, context)
if res:
# res有值代表处理过了APIException对象的异常了,返回的数据再定制
res = Response(data={'code': 998, 'msg': res.data.get('detail', '服务器异常,请联系系统管理员')})
# res = Response(data={'code': 998, 'msg': '服务器异常,请联系系统管理员'})
# res.data.get从响应中获取原来的处理详细信息
else:
res = Response(data={'code': 999, 'msg': str(exc)})
print(exc) # list index out of range
'''模拟日志处理'''
request = context.get('request') # 当次请求的request对象
view = context.get('view') # 当次执行的视图类对象
print('错误原因:%s,错误视图类:%s,请求地址:%s,请求方式:%s' % (str(exc), str(view), request.path, request.method))
'''结果:
错误原因:list index out of range,错误视图类:<app01.views.TestView object at 0x000001C3B1C7CA58>,请求地址:/test/,请求方式:GET
'''
return res
配置文件
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.exception.myexception_handler' # 再出异常,会执行自己定义的函数
}
REST framework定义的异常
-
APIException 所有异常的父类
-
ParseError 解析错误
-
AuthenticationFailed 认证失败
-
NotAuthenticated 尚未认证
-
PermissionDenied 权限决绝
-
NotFound 未找到
-
-
NotAcceptable 要获取的数据格式不支持
-
Throttled 超过限流次数
-
ValidationError 校验失败
也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。
自动生成接口文档
REST framework可以自动帮助我们生成接口文档。
接口文档以网页的方式呈现。
自动接口文档能生成的是继承自APIView
及其子类的视图。
接口文档 coreapi,swagger 安装依赖:REST framewrok生成接口文档需要coreapi库的支持。 pip3 install coreapi 使用步骤: 1 在urls.py 路由中 from rest_framework.documentation import include_docs_urls urlpatterns = [ path('doc/', include_docs_urls(title='图书管理项目接口文档')), ] 2 在settings.py 配置文件中 REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', } 3 在view.py 视图类中对应的方法上加注释即可 4 如果是ModelViewSet from app01 import models from app01 import serializer from rest_framework.viewsets import ModelViewSet from rest_framework.filters import OrderingFilter class BookView(ModelViewSet): """ list: 返回图书列表数据,通过Ordering字段排序 retrieve: 返回图书详情数据 latest: 返回最新的图书数据 read: 查询单个图书接口 """ queryset = models.Book.objects.all() serializer_class = serializer.BookModelSerializer # 排序 filter_backends = [OrderingFilter,] ordering_fields = ['price','name'] 5 字段描述,写在models.py的help_text上 from django.db import models class Book(models.Model): name = models.CharField(max_length=34,help_text='名字字段,字符串') price = models.IntegerField(help_text='价格字段,整型') 6 浏览的地址(浏览器中) http://127.0.0.1:8000/doc/ # 如果继承的是其它视图类,直接在对应的def函数下面写注释即可,例: class BookView(APIView): def get(self, request): """ 所有图书信息 :param request: :return: """ res = models.Book.objects.all() ser = serializer.BookModelSerializer(instance=res, many=True) return Response(ser.data)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性