序列化和反序列化
# api接口开发,最核心最常见的一个过程就是序列化
# 序列化: 把我们识别的数据转换成指定的格式提供给别人。
例如:我们在django中获取到的数据默认是模型对象(queryset),但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。
# 反序列化:把别人提供的数据转换/还原成我们需要的格式。
例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中
# 序列化:drf称为 read 序列化
# 反序列化:drf称为 write 反序列化
序列化和反序列化
# api接口开发,最核心最常见的一个过程就是序列化
# 序列化: 把我们识别的数据转换成指定的格式提供给别人。
例如:我们在django中获取到的数据默认是模型对象(queryset),但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。
# 反序列化:把别人提供的数据转换/还原成我们需要的格式。
例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中
# 序列化:drf称为 read 序列化
# 反序列化:drf称为 write 反序列化
基于APIView的5个接口
视图类
from rest_framework.views import APIView # APIView继承了djagno原来的View
from .serializer import BookSerializer
from rest_framework.response import Response
class BookView(APIView):
# 查询所有
def get(self, request):
book_list = Book.objects.all()
# drf提供了序列化类(先别关注)
ser = BookSerializer(instance=book_list, many=True) # 序列化
return Response({'code': 100, 'msg': '成功', 'result': ser.data})
def post(self, request):
ser = BookSerializer(data=request.data) # 反序列化
if ser.is_valid(): # 数据校验---》有些不合法的禁止
ser.save() # 保存到数据库中
return Response({'code': 100, 'msg': '成功'})
class BookDetailView(APIView):
# 查询单条
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, many=False) # 序列化
return Response({'code': 100, 'msg': '成功', 'result': ser.data})
# 修改一条
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data) # 反序列化
if ser.is_valid(): # 数据校验---》有些不合法的禁止
ser.save() # 保存到数据库中
return Response({'code': 100, 'msg': '成功'})
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
序列化类
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
路由
urlpatterns = [
path('books/', BookView.as_view()),
path('books/<int:pk>/', BookDetailView.as_view()),
]
CBV源码分析
# cbv写法:
1 视图中写视图类,继承View,写跟请求方式同名的方法
class BookView(View):
def get(self,request):
return 四件套
2 在路径用写
path('books/', BookView.as_view())
# 如上写法,为什么能够执行
# 前置条件:前端请求,一旦路径匹配成功,就会执行 BookView.as_view()(request传入,)
# 入口在 BookView.as_view()--->执行结果---》View中有个as_view类的绑定方法
@classmethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs)
res=self.dispatch(request, *args, **kwargs)
return res
return view
# 执行结果是view 的内存地址: 请求来了,执行view(request)
path('books/', view)
# 执行 View类中的as_view方法中的内层的view函数,路由匹配成功,本质是在执行
self.dispatch(request, *args, **kwargs)
# self是谁的对象?BookView的对象
# 去BookView中dispatch,找不到,去父类,View中找到了
# View这个类的dispatch
def dispatch(self, request, *args, **kwargs):
# request.method.lower() 如果是get请求, ‘get’ 在这个列表里面
if request.method.lower() in self.http_method_names:
# handler=getattr(BookView的对象,'get')
# handler就是BookView类中的get方法
handler = getattr(self, request.method.lower())
else:
handler = self.http_method_not_allowed
# 执行 BookView类中的get方法 (request)
return handler(request, *args, **kwargs)
# 最终本质跟写fbv的执行流程一样
# 最终结论:什么请求方式,就会执行视图类中的什么方法
APIView执行流程分析
# 有了drf,后期都写CBV,都是继承APIView及其子类
# 执行流程:
-入口:path('books/', BookView.as_view())---》请求来了,执行BookView.as_view()(request)
-as_view 是谁的? APIView的as_view
@classmethod
def as_view(cls, **initkwargs):
# super()代指的是:父类对象 View类的对象
# View的as_view(**initkwargs)----》执行结果是view,是View类的as_view方法中的view
view = super().as_view(**initkwargs)
view=csrf_exempt(view) # 局部禁用csrf,
return view
-path('books/', View类的as_view中的view,只是去掉了csrf的认证)
-请求来了,执行 【View类的as_view中的view,只是去掉了csrf的认证(request)】
-执行:self.dispatch(request, *args, **kwargs), self要从根上找
-self.dispatch 是APIView的dispatch,源码如下
def dispatch(self, request, *args, **kwargs):
# request 是新的request, request是老的request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
# 执行了认证,权限和频率
self.initial(request, *args, **kwargs)
# 在执行视图类方法之前,去掉了csrf认证,包装了新的request,执行了认证频率和权限
#### 执行请求方式字符串对应的方法
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
# 无论是在三大认证,还是视图类的方法中,出现错误,都会被异常捕获,统一处理
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
# 总结:
1 以后只要继承APIView的所有视图类的方法,都没有csrf的校验了
2 以后只要继承APIView的所有视图类的方法 中的request是新的request了
3 在执行视图类的方法之前,执行了三大认证(认证,权限,频率)
4 期间除了各种错误,都会被异常捕获,统一处理
# 补充(装饰器语法糖):
fbv,局部禁用csrf,如何写?
@csrf_exempt
def index(request):
pass
本质原理是(装饰器本质):index=csrf_exempt(index)