APIView执行流程、Request对象源码分析、序列化器介绍和快速使用、反序列化、反序列化的校验
APIView执行流程
1.APIView
drf只能在django上进行使用,安装了drf之后,导入一个视图类APIView(继承django的view),在后期使用drf写视图类 ,都是继承APIView及其子类
# 特点
1.继承APIView父类(Django中view的子类)
2.具有view的所有特征
3.提供了认证、授权、限流等功能
2.基于APIView+JsonResponse 写接口
models.py:
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
# 1 基于APIView+JsonResponse 写接口
class BookView(APIView):
def get(self,request):
books = Book.objects.all()
book_list = []
for book in books:
book_list.append({'name':book.name,'price':book.price,'publish':book.publish})
return JsonResponse(book_list,safe=False)
-
基于APIView+Response 写接口
# 2 基于APIView+Response 写接口
class BookView(APIView):
def get(self,request):
books = Book.objects.all()
book_list = []
for book in books:
book_list.append({'name':book.name,'price':book.price,'publish':book.publish})
return Response(book_list) # 列表或者字典可以序列化
4.APIView的执行流程
# 路由中的path('books/', views.BookView.as_view())---->执行views.BookView.as_view()(),现在的as_view是APIView的as_view
@classmethod
def as_view(cls, **initkwargs):
# 调用父类的as_view,父类是django原生的View
# 把djagno原生View的as_view方法中的闭包函数view拿出来
view = super().as_view(**initkwargs)
# csrf_exempt排除所有的csrf认证,相当于所有方法上加了装饰器
return csrf_exempt(view)
# 路由匹配成功,执行 csrf_exempt(view)(requets)--->View的as_view中的闭包函数view---》self.dispatch---->self是视图类的对象---》BookiView---》就是APIView的dispatch
def dispatch(self, request, *args, **kwargs):
# 参数的request是原来的django原生的request
# 下面的request,变成了drf提供的request类的对象
request = self.initialize_request(request, *args, **kwargs)
# self是视图类的对象,视图对象.request=request 新的request
self.request = request
try:
# 执行了认证,频率,权限
self.initial(request, *args, **kwargs)
# 原来的View的dispatch的东西
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
总结APIView的执行流程:
1.只有继承APIView都没有csrf的认证
2.包装了新的request,以后视图类中使用的request对象,已经变成drf提供的request类的对象
3.在执行视图类的方法之前,执行了3大认证(认证,权限,频率)
4.在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理
Request对象源码分析
原生的django的request是这个类的对象:
django.core.handlers.wsgi.WSGIRequest
drf的request是这个类的对象:
from rest_framework.request import Request
方法 __getattr__ 对象.属性,属性不存在会触发它的执行
在视图类的方法中,执行request.method ,新的request是没有method的,就触发了新的Request的__getattr__方法的执行
def __getattr__(self, attr):
# 如果取的属性不存在,会去原生的django的request对象中取出来
try:
# 反射:根据字符串获取属性或者方法,self.request是原来的request
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
以后用方法或者属性的时候,直接用通过反射从原来的request中取出来
request.query_params----->查询参数,reestful规范请求地址中带查询参数
request.FILES----->前端提交过来的数据,我们可以在这里提取
总结:
1.新的request取不到,就会去取老的__getattr__
2.request.data无论什么编码,什么请求方式,只要body中的数据,都可以在其中取出来
3.request.query_params就是原来的request._request.GET
4.上传的文件从request.FILES
魔法方法:
__str__ 打印对象会调用
__init__ 类()调用
__call__ 对象()调用
__str__ 打印对象会调用
__getattr__ 对象.属性 当对象获取的属性不存在时,返回获取这个不存在的属性名
序列化器-Serializer介绍和快速使用
序列化器的作用:
1.序列化:序列化器会把模型对象转换成字典,经过response以后变成json字符串
2.反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器完成数据校验功能,然后把字典转成模型
1.序列化多条
serializer.py--BookSerializer类
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
# 序列化字段
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
views.py--->BookView类
from .serializer import BookSerializer
class BookView(APIView):
def get(self,request):
books = Book.objects.all()
# 使用序列化类来完成
ser = BookSerializer(instance=books,many=True)
# instance要序列化的对象是books queryset对象
# many=True只要是queryset对象要传many=True,如果是单个对象就不用传
return Response(ser.data)
2.序列化单条
视图类---》BookDetailView
class BookDetailView(APIView):
def get(self,request,*args,**kwargs):
books = Book.objects.filter(pk=kwargs.get('pk')).first()
# 使用序列化类来完成
ser = BookSerializer(instance=books,)
# instance要序列化的对象是books queryset对象
# many=True只要是queryset对象要传many=True,如果是单个对象就不用传
return Response(ser.data)
序列化类
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
# 序列化字段
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
url
urlpatterns = [
path('books/<int:pk>/', views.BookDetailView.as_view()),
]
反序列化
1.反序列化的新增
序列化类
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book
class BookSerializer(serializers.Serializer):
# 序列化字段
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
def create(self, validated_data):
# 保存到数据库
book = Book.objects.create(**validated_data)
return book
视图类
from .serializer import BookSerializer
class BookView(APIView):
def post(self,request):
# 吧前端传入的数据给data参数
ser = BookSerializer(data=request.data)
# 校验数据
if ser.is_valid():
# 保存,调用ser.save,自动触发写的create,将数据保存起来
ser.save()
return Response({'code':100,'msg':'新增成功','result':ser.data})
else:
return Response({'code':101,'msg':ser.errors})
2.反序列化的修改
序列化类
class BookSerializer(serializers.Serializer):
# 序列化某些字段,这里写要序列化的字典
name = serializers.CharField() # serializers下大致跟models下的类是对应的
price = serializers.CharField()
publish = serializers.CharField()
def update(self, instance, validated_data):
# instance 要修改的对象
# validated_data 校验过后的数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save() # orm的单个对象,修改了单个对象的属性,只要调用对象.save,就能把修改保存到数据库
return instance
视图类
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
# 反序列化保存 ---借助于序列化类
ser = BookSerializer(data=request.data, instance=book)
if ser.is_valid():
ser.save() # 由于没有重写update,所以这报错
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
3.反序列化的删除
class BookDetailView(APIView):
def delete(self, requset, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
反序列化的校验
局部钩子与全局钩子
# 反序列化校验的局部钩子 ,名字不能以sb开头
def validate_name(self,name):
# 校验name是否合法
if name.startswith('s'):
raise ValidationError('错误')
else:
return name
# 全局钩子
def validate(self, attrs):
if attrs.grt('name') == attrs.get('publish'):
raise ValidationError('名字不能一致')
else:
return attrs
标签:__,serializers,APIView,self,request,源码,序列化
From: https://www.cnblogs.com/zx0524/p/17084313.html