day49-rest框架
1配置
在django框架下安装两个三方库
pip install djangorestframework
pip install django-filter
然后在当前应用的urls中配置路由
在路由文件的urlpatterns之前添加代码;作用分别是声明路由对象;注册一个student资源,资源对应StuView类
router = SimpleRouter()
router.register('student', views.StuView)
在路由文件的urlpatterns之后添加如下代码;作用是将路由添加到urlpatterns中
urlpatterns += router.urls
2对象序列化
在当前应用下的views文件下定义一个类;该类能够实现对数据库的查看、修改及删除、添加功能;这些功能都是通过继承父类来获得的;各个继承的类的作用如下。该方法主要针对资源(资源属于一个类)进行操作
mixins.ListModelMixin, 查看所有资源,GET
mixins.RetrieveModelMixin, 查看指定id的资源 ,GET
mixins.DestroyModelMixin, 删除指定的资源 ,DELETE
mixins.CreateModelMixin, 创建资源 ,POST
mixins.UpdateModelMixin 修改资源 ,PUT/PATCH
class StuView(viewsets.GenericViewSet,
mixins.ListModelMixin, # 查看所有资源,GET
mixins.RetrieveModelMixin, # 查看指定id的资源 ,GET
mixins.DestroyModelMixin, # 删除指定的资源 ,DELETE
mixins.CreateModelMixin, # 创建资源 ,POST
mixins.UpdateModelMixin): # 修改资源 ,PUT/PATCH
指定资源返回的内容
queryset = Student.objects.all()
#只查看所有is_delete属性为0的学生
# queryset = Student.objects.filter(is_delete=0)
资源(queryset)序列化的结果
serializer_class = StuSerializer
查询所有信息时,过滤掉被删除(is_delete=0)的学生信息
def get_queryset(self):
queryset = self.queryset
return queryset.filter(is_delete=0)
删除时不将数据从数据库删除,而是修改其is_delete为1
def perform_destroy(self, instance):
instance.is_delete=1
instance.save()
queryset = Student.objects.all()语句为获取指定资源返回的内容
serializer_class = StuSerializer语句为将获取的资源序列化(StuSerializer为定义的序列化类)
在过滤信息时:
queryset = Student.objects.all()
serializer_class = StuSerializer
def get_queryset(self):
queryset = self.queryset
return queryset.filter(is_delete=0)
以上部分可以被以下部分代替
queryset = Student.objects.filter(is_delete=0)
serializer_class = StuSerializer
由于不能轻易从数据库删除数据,故通常将要删除的对象的is_delete属性修改为1,而查看时,只看属性是0的,从而达到屏蔽效果。所以需要先在models中添加以下代码:
is_delete = models.BooleanField(default=0)
然后在数据库的查询中添加以下代码
alter table student add is_delete bit default 0;
当需要对浏览器获取的数据进行修改添加获取状态等信息时;还需要在下面继续添加代码
def retrieve(self, request, *args, **kwargs):
try:
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
except Exception as e:
return Response({'code': 404, 'msg': '获取失败', 'data': ''})
上面部分除了返回值其他都是固定写法
3序列化参数校验及返回具体值
上面的对象序列化都是在调用序列化的方法,而本节的序列化参数校验则是指定如何序列化及返回哪些值及对部分值进行修饰。
在当前应用下新建一个serializers.py文件
3.1定义序列化类
from rest_framework import serializers
from app.models import Student
class StuSerializer(serializers.ModelSerializer):
对传入的s_name进行校验
s_name = serializers.CharField(max_length=10, min_length=2,
error_messages={'required': '姓名必填',
'max_length': '最大不能超过10字符',
'min_length': '最小不能小于2字符'})
class Meta:
指定序列化的模型
model = Student
指定序列化后返回哪些内容
fields = ['s_name', 's_gender', 's_age', 'id']
重构to_representation方法,使true和false显示为男女
def to_representation(self, instance):
data = super(StuSerializer, self).to_representation(instance)
data['s_gender'] = '男' if data['s_gender'] else '女'
return data
data = super(StuSerializer, self).to_representation(instance):继承父类的to_representation方法并传入类名,to_representation作用是对传入的对象instance作相关处理并序列化生成字典,如果没有处理过程则直接生成字典data。
4给前端返回指定格式数据
在把数据返回给前端前先对其进行处理,添加状态码及获取是否成功的信息
这个功能主要通过重写retrieve方法实现。
在应用下的views.py文件中的序列化类中重写retrieve方法
在重写方法之前,需要先在settings中配置rest_framework的相关信息
REST_FRAMEWORK = {
# 使用自定义的render方法
'DEFAULT_RENDERER_CLASSES':(
'utils.jsonrenderer.MyJSONRenderer',
)
}
重写方法如下
def retrieve(self, request, *args, **kwargs):
try:
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
except Exception as e:
return Response({'code': 404, 'msg': '获取失败', 'data': ''})
上面代码只能对获取失败的信息进行操作,所以需要在中间件文件夹下新建一个jsonrenderer.py文件
from rest_framework.renderers import JSONRenderer
class MyJSONRenderer(JSONRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
try:
当传入的请求失败时,对其进行解析
code = data['code']
msg = data['msg']
result = data['data']
except:
当传入请求成功时,由于没有对其进行组装,故只有data数据,
没有msg和code,会报错,所以给其赋值
code = 200
msg = '请求成功'
result = data
my_data = {
'code': code,
'msg': msg,
'data': result
}
调用父类的render方法接收my_render数据,使其返回为data
return super().render(my_data)
5接口(API)文档
接口文档必须说明以下内容
请求(请求方式,请求路由)
请求参数(各字段的名称及类型及其意义,以及是否必填)
响应()
响应参数
如下
请求
GET /user/student/
请求参数
s_name str 姓名 (必填)
s_age int 年龄 (非必填)
s_gender str 性别 (非必填)
math float 数学成绩 (非必填)
wuli float 物理成绩 (非必填)
响应
{
'code': 200,
'msg':'请求成功',
'data':[
{'s_name': '小明'},
{'s_age': 20},
{'s_gender': '男'}
]
}
响应参数
s_name str 学生姓名
s_gender str 性别
s_age int 年龄
6接口
在views中定义一个视图函数
def stu_list(request):
if request.method == 'GET':
return render(request, 'stu_list.html')
新建Html文档
<body>
<script>
$.ajax({
url: '/user/student/',
type: 'GET',
{#data: '',#}
dataType: 'json',
success: function (result) {
{#ajax异步请求#}
for(var i=0; i<result.data.length; i++){
var s = '<p>姓名: '+ result.data[i].s_name +' 性别:' +
' '+ result.data[i].s_gender + '年龄: '+
result.data[i].s_age + '<a onclick="del_stu(' +
result.data[i].id + ')">删除</a><a href="" ' +
'onclik="edit_stu(' + result.data[i].id +
')">编辑</a></p>'
{#在div标签后追加上面的内容,若将append写成html或者text则只加最后的一次#}
$('.stus').append(s)
}
console.log(result.data)
},
error: function (result) {
alert('失败')
}
});
function del_stu(id){
$.ajax({
url: '/user/student/' + id + '/',
type: 'DELETE',
dataType: 'json',
success: function (result) {
console.log(result)
{#删除后,重新跳向stu_list页面以刷新#}
location.href = '/user/stu_list/'
},
error: function(result){
alert('删除失败')
}
})
};
function edit_stu(id){
$.ajax({
url: '/user/student/' + id + '/',
type: 'PATCH',
data:{'s_name': '石头人'},
dataType: 'json',
success: function (data){
console.log(data)
},
error: function(data){
alert('修改失败')
}
})
};
function add_stu() {
$.ajax({
url: '/user/student/',
type: 'POST',
data:{'s_name': '墨菲特'},
dataType: 'json',
success: function (data) {
console.log(data)
},
error:function(data){
alert('失败')
}
})
}
</script>
<div class="stus">
<a onclick="add_stu();">添加</a>
</div>
</body>
该文档能够实现ajax的异步请求