前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象.
可以通过实现create()和update()两个方法来实现。
1.添加数据:
class BooksView(View):
def get(self,request):
# 添加数据
data_dict = {
'title': 'test1213',
'pub_data': '2019-10-11',
# 'read':-1, 模拟失败
'read': 2000,
'comment': 400,
}
serializers = BookSerializers(data=data_dict)
serializers.is_valid(raise_exception=True)
# drf不建议在这里写 最好写在序列化器类里面
# Student.objects.create(**serializers.validated_data)
serializers.save() # 保存数据
return JsonResponse(serializers.data)
# 调用序列化内部保存数据的方法[自动调用create或者update]
# 在源码save方法中 如果初始化序列化器时以是否传递了instance参数作为判断依据
# 如果传递了instance 则save方法中调用update进行更新数据
# 如果没有传递instance 则save方法中调用create进行数据创建
# 都需要在序列化器类中定义好这两个方法
保存数据源码:
在源码save方法中 如果初始化序列化器时以是否传递了instance参数作为判断依据
如果传递了instance 则save方法中调用update进行更新数据
如果没有传递instance 则save方法中调用create进行数据创建
都需要在序列化器类中定义好这两个方法
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
assert self.instance is not None, (
'`update()` did not return an object instance.'
)
else:
self.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)
2.更新数据:
class BooksView(View):
def get(self,request):
# 更新数据
data_dict = {
'title': 'test',
'pub_data': '2019-10-11',
# 'read':-1, 模拟失败
'read': 2000,
'comment': 400,
}
pk = 9
book_obj = Book.objects.get(pk=pk)
serializers = BookSerializers(instance=book_obj,data=data_dict)
serializers.is_valid(raise_exception=True)
serializers.save()
return JsonResponse(serializers.data)
序列化器类中:
# 保存数据
# 两个方法:内置的
# 第一种 create
def create(self, validated_data):
'''添加数据'''
# validated_data.pop 删除数据
instance = models.Book.objects.create(**validated_data)
return instance
# 第二种 update
def update(self, instance, validated_data):
'''修改数据'''
instance.title = validated_data.get('title')
instance.pub_data = validated_data.get('pub_data')
instance.read = validated_data.get('read')
instance.comment = validated_data.get('comment')
# 下面的save是调用了ORM中提供给模型保存数据的save 不是序列化器中的save
instance.save()
return instance
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer相同,但提供了:
定义:
__all__
表名包含所有字段,也可以写明具体哪些字段定义模型类:
from rest_framework import serializers
class BookModelSerializers(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
# exclude = ['xx'] # 排除
extra_kwargs = {
'title':{'error_messages':{'max_length':'不能大于30个字符!!!'}}
}
视图中:
class BooksModelView(View):
# 展示所有的数据
def get1(self,request):
# 序列化展示数据
book_list = Book.objects.all()
serializers = BookModelSerializers(instance=book_list,many=True)
return JsonResponse(serializers.data,safe=False)
# 展示一条数据
def get2(self, request,pk):
# 序列化展示数据
book_list = Book.objects.get(pk=pk)
serializers = BookModelSerializers(instance=book_list)
return JsonResponse(serializers.data)
def get(self,request):
'''反序列化校验数据'''
data_dict = {
'title': 'test',
'pub_data': '2019-10-11',
# 'read':-1, 模拟失败
'read': 2000,
'comment': 400,
}
serializers = BookModelSerializers(data=data_dict)
serializers.is_valid(raise_exception=True) # 数据校验
print(serializers.errors) # 错误信息
print(serializers.data) # 序列化后的数据
print(serializers.validated_data) # 正确信息数据
serializers.save()
return JsonResponse(serializers.data)
1.Request:
REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。
REST framework 提供了Parser解析器类,在接收到request请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中。
Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。
无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。
常用属性:
.data:
request.data` 返回解析之后的请求体数据。
类似于Django中标准的request.POST和request.FILES属性,
但提供如下特性:
包含了解析之后的文件和非文件数据
包含了对POST、PUT、PATCH请求方式解析后的数据
利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
.query_params:
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
2.Response:
REST framework提供了一个响应类Response
,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染器对象)成符合前端需求的类型。
REST framework提供了Render
渲染器,用来根据请求头中的Accept
(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。
构造方式:
Response(data, status=None, template_name=None, headers=None, content_type=None)
data
数据不要是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用renderer
渲染器处理data
。
data
不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer
序列化器序列化处理后(转为了Python字典类型)再传递给data
参数。
参数说明:
data
: 为响应准备的序列化处理后的数据
status
: 状态码,默认200
template_name
: 模板名称,如果使用HTMLRenderer
时需指明
headers
: 用于存放响应头信息的字典
content_type
: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
常用属性:
.data:传给response对象的序列化后,但尚未render处理的数据
.status_code:状态码的数字
.content:经过render处理后的响应数据
示例:
from student.models import Student
from rest_framework.views import APIView
from student.serializers import StudentModelserializers
from rest_framework.response import Response
from rest_framework import status
class StudentView(APIView):
def get(self, request):
print(request) # drf的request对象
print(request._request) # django原生的request
print(request.query_params) # 获取查询参数
print(request.data) # 请求体数据
student_list = Student.objects.all()
serializers = StudentModelserializers(instance=student_list, many=True)
return Response(serializers.data,status=status.HTTP_200_OK) # Response对象
DRF专门封装了状态供我们使用:
from rest_framework import status
APIView
是REST framework提供的所有视图的基类,继承自Django的View
父类。
APIView
与View
的不同之处在于:
Request
对象,而不是Django的HttpRequeset
对象;Response
对象,视图会为响应数据设置(render)符合前端要求的格式;APIException
异常都会被捕获到,并且处理成合适的响应信息;支持定义的属性
在APIView
中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。
示例:
from rest_framework.views import APIView
from student.models import Student
from student.serializers import StudentModelserializers
from rest_framework.response import Response
from rest_framework import status
class StudentView(APIView): # 继承APIView
def get(self, request):
# 展示数据
student_list = Student.objects.all()
serializers = StudentModelserializers(instance=student_list, many=True)
return Response(serializers.data, status=status.HTTP_200_OK)
def post(self,request):
# 添加数据
data = request.data
serializers = StudentModelserializers(data=data)
serializers.is_valid(raise_exception=True)
serializers.save()
return Response(serializers.data)
结果:
可以在rest_framework的settigns.py中看到:
点击json会返回json类型的数据,不再是rest_framework的api页面,默认是api页面
继承自APIVIew
,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。
属性:
**serializer_class:**指明视图使用的序列化器
queryset: 指明使用的数据查询集
方法:
get_queryset(self):
返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset
属性
get_object(self):
返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。
在试图中可以调用该方法获取详情信息的模型类对象。
get_serializer(self, *args, **kwargs):
返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。
示例:
from rest_framework.generics import GenericAPIView
class StudentGenericAPIView(GenericAPIView):
# 指明序列化器类
serializer_class = StudentModelserializers
# 指明数据查询集
queryset = Student.objects.all()
def get(self,request):
# 展示数据
serializers = self.serializer_class(instance=self.get_queryset(),many=True)
return Response(serializers.data)
def post(self,request):
# 添加数据
data = request.data
serializers = self.serializer_class(data=data)
serializers.is_valid(raise_exception=True)
serializers.save()
return Response(serializers.data)
在drf中提供了五个不同视图扩展类,里面封装了五个不同的http请求方法,用于和GenericAPIView实现代码的简写:
示例:
from rest_framework.mixins import CreateModelMixin,ListModelMixin
class Student3GenericAPIView(GenericAPIView,CreateModelMixin,ListModelMixin):
serializer_class = StudentModelserializers
queryset = Student.objects.all()
def get(self,request):
# 展示数据
return self.list(request)
def post(self,request):
# 添加数据
return self.create(request)
可以看到,代码简洁了很多,但是为什么直接可以返回一个list就会展示数据,返回create就会创建数据呢,看一下源码:
class Student4GenericAPIView(GenericAPIView,DestroyModelMixin):
def delete(self,request,pk):
return self.destroy(request,pk)
DestroyModelMixin源码分析:
首先看get_object:
get_object方法上面定义两个变量:
那么这个self.kwargs是在哪里传递进来的呢?
发现GenericAPIView继承自APIView:
但是APIView自己又没有初始化的方法,那么还要考虑self.kwargs的数据是在哪里传进来的,上面刚说到APIView继承View,这个View就是django的View,点进去看一下,下面这张图可以看到这里有初始化方法,并且有kwargs:
具体的删除流程如下:
1.在View中取出传递进来的参数
2.通过字典取值的方式将传递进来的pk值获取出来,组成一个字典
3.使用视图开展类DestroyModelMixin中的destroy方法将数据删除
4.如果获取不到具体的查询集则抛出Http404
在上面的使用过程中 都是视图类继承GenericAPIView和视图扩展类Mixins来实现简写的
但是简写的不够彻底 所以在drf中还可以进一步简化,drf基于GenericAPIView和视图扩展类 衍生出了多个视图子类。
from rest_framework.generics import CreateAPIView,ListAPIView,DestroyAPIView
class Student5GenericAPIView(CreateAPIView,ListAPIView,DestroyAPIView):
serializer_class = StudentModelserializers
queryset = Student.objects.all()
这里已经将所有的方法都写好了,和我们上面使用视图扩展类Mixins里面写的代码一样,这里只需要继承视图扩展类的子类就可以全部搞定:
总结:
APIView:视图基类
GenericAPIView:通用视图类
视图扩展类:mixins 一共五个
视图扩展子类:generics 一共七个
视图扩展类:
ListModelMixin:获取所有数据
CreateModelMixin:创建一条数据
RetrieveModelMixin:获取一条数据
UpdateModelMixin:更新一条数据
DestroyModelMixin:删除一条数据
视图扩展子类:
CreateAPIView 添加一条数据
ListAPIView 获取所有数据
UpdateAPIView 更新一条数据
RetrieveAPIView 获取一条数据
DestroyAPIView 删除一条数据
RetrieveUpdateDestroyAPIView 获取一条数据 更新一条数据 删除一条数据
RetrieveUpdateAPIView 获取一条数据 更新一条数据