DjangoRESTframework-前端对接
前端对接
前后端分离的项目,后端开发不涉及前端页面开发,前端开发人员按照API文档去访问后端数据,然后渲染页面。前端开发好对应的功能后,和后端进行配合就可以看到效果了。
前端环境其实就是 一些前端的代码和资源文件,包括 js文件、html文件、css文件 还有 图片视频文件
等。 dist压缩包后,解压到项目根目录下面,这个目录下面就是前端的代码资源文件。
Django的开发环境也可以从浏览器访问这些前端的资源文件。但是前端文件都是静态文件,需要配置一下Django的配置文件, 指定http请求如果访问静态文件,Django在哪个目录下查找。
注意,接下来我们配置 Django 静态文件服务, 是 开发时 使用的一种临时方案 ,性能很低,这是方便我们调试程序用的。 正式部署web服务的时候,不应该这样干,应该采用其它方法,比如Nginx等。
配置前端文件访问路径
主路由文件配置
打开项目目录下的urls.py
文件,在urlpatterns
末尾添加+static('/', document_root='dist')
指的是在url 路由中加入前端静态文件的查找路径
from django.contrib import admin
from django.urls import path,include
from sqtp import urls as sqtp_urls
from django.conf.urls.static import static # 静态文件服务
urlpatterns = [
path('admin/', admin.site.urls),
path('api/',include(sqtp_urls)),
]+static('/', document_root='dist')
同时需要对后端的接口主路由进行修改,这样如果 http请求的url 不是以 api/xxx
开头, Django 就会默认是要访问 dist目录下面的静态文件。
启动项目,在浏览器中输入http://127.0.0.1:8888/index.html
访问首页
接口完善开发
此时测试用例页面是还没有数据的,需要去添加数据。测试用例Case的数据,要返回到前端页面上,需要有模型和序列化器,模型已经创建了,现在需要添加序列化器
修改sqtp的目录下的 serializers.py
文件,添加用例部分的序列化器
# 用例Case部分序列化器
class CaseSerializer(serializers.ModelSerializer):
class Meta:
model = Case
fields = '__all__'
在sqtp
应用app目录下的views.py
文件添加视图集
# 添加Case视图集
class CaseViewSet(viewsets.ModelViewSet):
queryset = Case.objects.all() # 数据的查询集
serializer_class = CaseSerializer # 指定序列化器
在sqtp
应用app目录下的urls.py
文件配置路由,将视图信息注册到路由列表
router = DefaultRouter()
router.register(r'requests',sqtp_view.RequestViewSet) # 将Request视图信息注册路由列表
router.register(r'cases',sqtp_view.CaseViewSet) # 将Case视图信息注册路由列表
urlpatterns = [
path('',include(router.urls)),
path('swagger/',schema_view.with_ui('swagger',cache_timeout=0),name='schema-swagger-ui'), #互动模式
path('redoc/',schema_view.with_ui('redoc',cache_timeout=0),name='schema-redoc'), #文档模式
# path('testing/',sqtp_view.testing_api),
]
启动项目,浏览器中输入http://127.0.0.1:8888/api/swagger/
启动 swagger API文档生成器,可以发现这里如果要新增数据,需要填写config信息,因为 Case模型与Config模型是一对一关联,数据库中Case表通过config字段与Config表进行数据关联
如果Config表中没有对应的数据,那么通过接口新增数据就会失败,抛出异常无效主键 “0” - 对象不存在
,所以需要先手动在Config表中插入一条数据,然后再通过接口进行传参新增数据
数据新增成功后,前端页面通过接口返回内容展示了一条数据
嵌套字段
为了提供更多的信息给前端,需要对目前的接口进行开发完善。以用例为例,当前的查询接口返回的消息是这种格式:
{
"msg": "success",
"retcode": 200,
"retlist": [
{
"id": 2,
"file_path": "demo_case.json",
"config": 2,
"suite": null
}
]
}
其中config只有id表示,没有具体的信息,如果前端想要获取config信息将会比较麻烦,所以直接通过后端提供相关数据效果比较好点。
使用REST框架,这个问题交给序列化器就可以处理了。目前默认的序列化器很简单,只简单的定义了要展示的字段和对应模型。那么,默认情况下序列化器只会提取外键字段的id作为默认值,所以需要额外定义需要展示嵌套字段的关联数据。
这个问题处理起来也非常简单,只需指定config为对应的序列化器对象即可
修改sqtp的目录下的 serializers.py
文件,添加Config部分的序列化器,并在用例Case部分序列化器中指定嵌套的方式,指定config为嵌套字段。注意两个类的顺序,由于python引用前需要先定义,所以ConfigSerializer要在上面
# 配置config部分序列化器
class ConfigSerializer(serializers.ModelSerializer):
class Meta:
model = Config
fields = '__all__'
# 用例Case部分序列化器
class CaseSerializer(serializers.ModelSerializer):
config = ConfigSerializer() # config字段对应Config序列化器返回的内容,REST会自动提取其值
class Meta:
model = Case
fields = '__all__'
接口返回内容中就多了一层config信息的嵌套
{
"msg": "success",
"retcode": 200,
"retlist": [
{
"id": 2,
"config": {
"id": 2,
"name": "测试002",
"base_url": null,
"variables": null,
"parameters": null,
"export": null,
"verify": true
},
"file_path": "demo_case.json"
}
]
}
页面也展示了对应的用例名称
choice字段内容展示
request接口中,method字段这里显示的不是GET/POST/PUT/DELETE
,而是数字0~3
这种实际存储在数据中的值。
{
"msg": "success",
"retcode": 200,
"retlist": [
{
"id": 39,
"method": 0,
"url": "/api/teacher/",
"params": null,
"headers": null,
"cookies": null,
"data": {
"name": "小王老师",
"courses": "英语",
"address": "广东深圳"
},
"json": null,
"step": null
}
]
}
这是因为Request模型中,这个字段的定义的是choices
选择字段。但是接口中不会显示响应的注释,所以这里需要修改成显示成对应的可读内容。
解决这个问题之前,可以看下django原生ORM是如何显示choice字段的可读内容的。执行python manage.py shell
命令进入django shell
>>> from sqtp.models import Request
>>> req = Request.objects.all().first()
>>> req.method
0
>>> req.get_method_display()
'GET'
req.method
默认情况下还是显示实际值,采用get_field_display
方法,显示的内容就是field对应choice字段的名称
修改sqtp的目录下的 serializers.py
文件,修改Request部分序列化器,修改字段的获取方式
# 请求Request部分序列化器 命名规范:模型名+Serializer
class RequestSerializer(serializers.ModelSerializer): # 继承 Serializer
method = serializers.SerializerMethodField() # 自定义字段序列化返回方法
def get_method(self, obj): # rest框架获取method时,自动调用该方法
return obj.get_method_display() # 返回choice的 displayname而不是实际值
class Meta:
model = Request # 指定序列化器对应的模型
# fields = ['step','method','url','params','headers'] # 指定序列化模型中的字段
fields = '__all__' # 序列化所有字段
此时重新访问接口,method字段返回了可读内容
{
"msg": "success",
"retcode": 200,
"retlist": [
{
"id": 39,
"method": "GET",
"url": "/api/teacher/",
"params": null,
"headers": null,
"cookies": null,
"data": {
"name": "小王老师",
"courses": "英语",
"address": "广东深圳"
},
"json": null,
"step": null
}
]
}