今日内容概要
1.反序列化类校验部分源码解析
2.断言
3.drf请求
4.drf响应
5.视图组件和两个视图基类
6.基于GenericAPIView+5个视图扩展类
1.反序列化类校验部分源码解析
反序列化校验,什么时候,开始执行校验
视图类中的 ser.is_valid(),就会执行校验,校验通过返回True,不通过返回False
入口:ser.is_valid() 是序列化类的对象,假设序列化类是BookSerializer---》is_valid---》找不到,找到父类BaseSerializer中有 :【raise_exception:先注意】
def is_valid(self, *, raise_exception=False):
if not hasattr(self, '_validated_data'):
try:
self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
if self._errors and raise_exception:
raise ValidationError(self.errors)
return not bool(self._errors)
self._validated_data = self.run_validation(self.initial_data) 核心--》self序列化类的对象
切记一定不要按住ctrl键点击
真正的执行顺序是,从下往上找,找不到,再往上
最终从Serializer类中找到了run_validation,而不是Field中的run_validation
def run_validation(self, data=empty):
字段自己的,validates方法
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data
局部钩子----【局部钩子】
value = self.to_internal_value(data)
try:
self.run_validators(value)
全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单
value = self.validate(value)
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value
局部钩子 self.to_internal_value(data) ---》self是BookSerializer的对象,从根上找
def to_internal_value(self, data):
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
fields写在序列化类中一个个字段类的对象
for field in fields:
self BookSerializer的对象,反射validate_name
validate_method = getattr(self, 'validate_' + field.field_name, None)
try:
在执行BookSerializer类中的validate_name方法,传入了要校验的数据
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
2.断言
源码中大量使用try和断言
关键字assert ,有什么作用,断定你是xx,如果不是就抛异常
name = 'lqz'
if name == 'lqz':
print('对了')
else:
print('错了')
raise Exception('名字不为lqz,不能继续走了')
assert name=='lqz' 断定是,如果不是,就抛异常
print('后续代码')
3.drf请求
Request能够解析的前端传入的编码格式
需求是该接口只能接收json格式,不能接收其他格式
方式一,在继承自APIView及其子类的的视图类中配置(局部配置)
总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
parser_classes = [JSONParser,]
方式二:在配置文件中配置(影响所有,全局配置)
-django有套默认配置,每个项目有个配置
-drf有套默认配置,每个项目也有个配置---》就在django的配置文件中
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
方式三:全局配了1个,某个视图类想要3个,怎么配
只需要在视图类,配置3个即可
因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找
Request类有哪些属性和方法
视图类方法中的request
data
__getattr__
query_params
4.drf响应
Response能够响应的编码格式
drf 是djagno的一个app,所以要注册
drf的响应,如果使用浏览器和postman访问同一个接口,返回格式是不一样的
drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据
方式一:在视图类中写(局部配置)
两个响应类---》找---》drf的配置文件中找--》两个类
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
renderer_classes=[JSONRenderer,]
方式二:在项目配置文件中写(全局配置)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
方式三:使用顺序(一般就用内置的即可)
优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的
Response的源码属性方法
drf 的Response 源码分析
-from rest_framework.response import Response
-视图类的方法返回时,retrun Response ,走它的__init__,init中可以传什么参数
Response init可以传的参数
def __init__(self,
data=None,
status=None,
template_name=None,
headers=None,
exception=False,
content_type=None)
data:之前咱们写的ser.data 可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个
status:http响应的状态码,默认是200,你可以改
drf在status包下,把所有http响应状态码都写了一遍,常量
from rest_framework.status import HTTP_200_OK
Response('dddd',status=status.HTTP_200_OK)
template_name:了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制
headers:响应头,http响应的响应头
考你,原生djagno,如何像响应头中加东西
四件套 render,redirect,HttpResponse,JsonResponse
obj = HttpResponse('dddd')
obj['xxc'] = 'yyc'
return obj
content_type :响应编码格式,一般不动
重点:data,status,headers
5.视图组件和两个视图基类
drf 视图,视图类,学过APIView,drf的基类,drf提供的最顶层的类
APIView跟之前的View区别
传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
视图方法可以返回REST framework的Response对象-
任何APIException异常都会被捕获到,并且处理成合适的响应信息;
在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
两个视图基类
APIVIew
类属性:
renderer_classes 响应格式
parser_classes 能够解析的请求格式
authentication_classes 认证类
throttle_classes 频率类
permission_classes 权限类
基于APIView+ModelSerializer+Resposne写5个接口
APIView+ModelSerializer+Responce写5个接口
视图类
from .models import Book
from .serializer import BookSerializer
class BookView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data)
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books)
return Response(ser.data)
def put(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
序列化类
ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
路由
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
]
6.基于GenericAPIView+5个视图扩展类
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
ListModelMixin
基于GenericAPIView+5个视图扩展类写接口
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
视图类
class BookSerializer(serializers.ModelSerializer):
跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
路由
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
]
标签:ser,self,request,视图,data,drf
From: https://www.cnblogs.com/yueq43/p/17090234.html