一、 自定义接口规范(渲染器)
1. 渲染器的基本原理
序列化在返回数据后并不是直接做为响应数据,而是经过渲染器的渲染,生成不同格式的响应内容 。
重构渲染器就是重写父类渲染器的render方法 。
1
| render(self, data, accepted_media_type=None, renderer_context=None)
|
data
: 响应数据(序列化器的.data属性),等同于renderer_context[“ response “].data的值accepted_media_type=None
: 可选的。如果提供,这是由内容协商阶段确定的所接受的媒体类型。- 根据客户端的 Accept: 头,这可能比渲染器的 media_type 属性更具体,可能包括媒体类型参数。例如 “application/json; nested=true” 。
renderer_context=None
: 可选的。如果提供,这是一个由view提供的上下文信息的字典。- 默认情况下这个字典会包括以下键: view , request , response , args , kwargs 。
renderer_context[" view "]
对应调用的视图函数renderer_context[" request "]
对应本次请求对象,包含所有请求数据,如请求头,请求参数等等renderer_context[" response "]
对应本次响应对象,包含所有响应数据,如响应头,状态码,响应数据
2. REST 框架 渲染器配置
在 settings.py
中添加drf全局配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'utils.exception.my_exception_handler', 'DEFAULT_RENDERER_CLASSES': ( 'utils.renderers.MyRenderer', ) }
|
utils.renderers.MyRenderer
对应的是你文件路径
创建 utils 目录
,然后在下面新建 renderers.py
文件 和 exception.py
文件
3. 正常信息获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
from rest_framework.renderers import JSONRenderer
class MyRenderer(JSONRenderer): def render(self, data, accepted_media_type=None, renderer_context=None): resp_content = data if renderer_context: status_code = renderer_context['response'].status_code if str(status_code).startswith('2'): if not isinstance(resp_content, list): resp_content = [resp_content] res = {'msg': 'success', 'retcode': status_code, 'retlist': resp_content} return super().render(res, accepted_media_type, renderer_context) return super().render(resp_content, accepted_media_type, renderer_context)
|
3. 异常信息获取
REST 默认情况可以处理的异常有
- 在REST framework内部产生的 APIException 的子类异常。
- 原生Django的 Http404 异常.
- 原生Django的 PermissionDenied 异常.
异常处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
from rest_framework.views import exception_handler
def my_exception_handler(exc, context): response = exception_handler(exc, context) if response: response.data['msg'] = 'error' response.data['retcode'] = response.status_code response.data['error'] = str(exc) response.data.pop('detail') return response
|
二、 在线接口文档 —- swagger
Django REST Swagger 项目已经不维护了,并且不支持最新的Django
drf-yasg
项目作为接口文档生成器。yasg的功能非常强大,可以同时支持多种文档格式。
1. 配置安装
1. 安装最新版 drf-yasg
2. 注册
drf-yasg
属于django的插件,因此需要注册到配置文件中 settings.py
staticfiles
: 默认的静态文件。默认是已经注册了的,如果没有注册需要手动注册
1 2 3 4
| INSTALLED_APPS = [ 'django.contrib.staticfiles', 'drf_yasg', ]
|
3. 配置路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from drf_yasg.views import get_schema_view from drf_yasg import openapi
from rest_framework import permissions
swagger_view = get_schema_view( openapi.Info( title='SQPT API', default_version='v1', description='SQPT接口文档', terms_of_service='https://www.pupper.cn', contact=openapi.Contact(email='pupper.cheng@gmail.com'), license=openapi.License(name='BSD License'), ), public=True, permission_classes=(permissions.AllowAny,), )
urlpatterns = [ path('swagger/', swagger_view.with_ui('swagger', cache_timeout=0,)), path('redoc/', swagger_view.with_ui('redoc', cache_timeout=0,)), ]
|
2. 定制化用法(viewset 模式)
函数视图
: 采用swagger_auto_schema
装饰器 修饰视图函数
1 2 3 4 5 6 7 8
|
from drf_yasg.utils import swagger_auto_schema
@swagger_auto_schema(method='GET',operation_summary='定制化API',operation_description='接口描述。。') @api_view(['GET']) def customer_api(request): return Response(data={"retcode":status.HTTP_200_OK,'msg':'building...'})
|
类视图
: 采用 django 装饰器 配合 swagger 的 装饰器 来实现
1 2 3 4 5 6 7 8 9 10 11 12 13
|
from django.utils.decorators import method_decorator from drf_yasg.utils import swagger_auto_schema
@method_decorator(name='list', decorator=swagger_auto_schema(operation_description="列出所有步骤数据")) @method_decorator(name='create', decorator=swagger_auto_schema(operation_description="创建步骤")) @method_decorator(name='update', decorator=swagger_auto_schema(operation_description="更新步骤")) @method_decorator(name='destroy', decorator=swagger_auto_schema(operation_description="删除步骤")) @method_decorator(name='retrieve', decorator=swagger_auto_schema(operation_description="提取单个步骤数据")) class CaseViewSet(viewsets.ModelViewSet): queryset = Case.objects.all() serializer_class = CaseSerializer
|
三、 前端对接
前端样式地址 提取码:sqpt
配置 Django 静态文件服务, 是 开发时
使用的 一种 临时方案
,
在 autotpsite/urls.py 文件
中配置静态服务
1 2 3 4 5 6 7 8 9 10
|
from django.conf.urls.static import static
urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('sqpt.urls')),
]+static('/', document_root='dist')
|
如果 http请求的url 不是以 api/project 开头, Django 就会认为是要访问 dist目录下面的静态文件。
当我们访问html页面时,js代码会自动请求后台数据,渲染到当前页面上,为了适配前端,减少改动工作,先将后台URL进行改动
1 2 3 4 5
|
urlpatterns = [ path('api/', include('sqpt.urls')), ]
|
四、 接口开发完善
1. 嵌套字段内容显示
1 2
| {"msg":"success","retcode":200,"retlist": [{"id":1,"file_path":"haiwen_Test.yml","config":1,"suite":null}]}
|
显示 config 的具体内容:指定 config 为对应的序列化器对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
class ConfigSerializer(serializers.ModelSerializer): class Meta: model = Config fields = '__all__'
class CaseSerializer(serializers.ModelSerializer): config = ConfigSerializer() class Meta: model = Case fields = '__all__'
|
如果 ConfigSerializer
在 CaseSerializer
的 下方,那么 config = ConfigSerializer()
会报错
已经展示了config
嵌套字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "msg": "success", "retcode": 200, "retlist": [ { "id": 1, "config": { "id": 1, "name": "用例1", "base_url": "http://localhost", "variables": null, "parameters": null, "verify": false, "export": null }, "file_path": "haiwen_Test.yml", "suite": null } ] }
|
2. displayname
获取 method 具体的值:
1 2 3 4 5 6 7 8 9 10 11 12
|
class RequestSerializer(serializers.ModelSerializer): method = serializers.SerializerMethodField()
def get_method(self, obj): return obj.get_method_display()
class Meta: model = Request fields = '__all__'
|
重新访问接口,method字段返回了可读内容