反序列化类校验部分源码解析
# 反序列化校验,什么时候开始执行校验 视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回false # 反序列化类校验的入口: ser.is_valid() 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
断言
# 断言的关键字 assert : 断定你是XX,如果不是就抛异常 # 源码中大量使用了try和断言 # 断言的使用 name = 'tom'
# if name = 'tom': # print('对') # else: # raise Exception('名字不能是tom以外的') assert name='tom' # 断定是,不是直接抛异常 print('名字不能是tom以外的')
drf之请求
# 1.Request能够解析的前端传入的编码格式 # 方式一:继承来自APIView及其子类的视图类中配置(局部配置) from rest_framework.parsers import JSONParser,FormParser,MultiPartParser class BookView(APIView): # 我们所写的接口,只能接收某种编码格式,比如接收json格式 # parser_classes:解析类,意思是能够解析前端传入的什么编码格式[默认情况配了三个解析类,现在只需要配一个解析类] parser_classes = [JSONParser,] def post(self, request): # 请求中携带数据,都从request.data中取 print(request.data) # 如果是json格式编码,request.data就是普通dict # 如果是urlencoded,form-data格式编码,request.data就是普通django.http.request.QueryDict print(type(request.data)) return Response() # 方式二:直接在配置文件中配置(影响所有,全局配置) - django有套默认配置,每个项目有个配置 - drf有套默认配置,在django的配置文件中: REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': [ # 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', # 'rest_framework.parsers.MultiPartParser', ], } # 方式三:全局配了一个,某个视图类需要三个,如何配置: - 只需要在视图类,配置三个即可 - 因为:先从视图类自身找,找不到需要去项目drf配置中找,最后去drf默认配置中找
# 2.Request类有哪些属性和方法
- 视图类方法中的request
data
__getattr__
query_params
drf之响应
# drf 是django的一个app,所以要注册 # drf的响应,如果使用浏览器和postman访问,返回的格式不同 - 原因是drf做了判断,对于浏览器会返回好看一些,对于postman只会返回json数据 # 方式一:在视图类中写(局部配置) - 两个响应类--->在drf配置文件中找--->两个类 from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer class BookView(APIView): # 我们所写的接口,只能接收某种编码格式,比如接收json格式 # parser_classes:解析类,意思是能够解析前端传入的什么编码格式[默认情况配了三个解析类,现在只需要配一个解析类] # parser_classes = [JSONParser,] renderer_classes = [JSONRenderer,] def post(self, request): # 请求中携带数据,都从request.data中取 print(request.data) # 如果是json格式编码,request.data就是普通dict # 如果是urlencoded,form-data格式编码,request.data就是普通django.http.request.QueryDict print(type(request.data)) return Response() # 方式二:在项目配置文件中写(全局配置) REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ], } # 方式三:使用顺序(一般使用内置的就行) 优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的配置 # Response源码属性和方法 - drf源码分析 from rest_framework.response import Response - 视图类的方法返回时,return Response, 走自己的__init__, init中可以传入的参数有: def __init__(self, data=None, status=None, template_name=None, headers=None, exception=False, content_type=None) data: 1. 之前写的ser.data 可以是字典或列表,字符串 2. 序列化之后返回给前端 3.前端在响应体代码中看到的就是这个data status: 1.http响应的状态码,默认是200,可以改 2.drf在status包下,把所有http响应状态码都写一遍 3.from rest_framework.status import HTTP_200_OK 4.Response('dddd',status=status.HTTP_200_OK) template_name: 了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子 headers: 响应头,http响应头,如何在响应头中加东西 content_type : 响应编码格式,一般不动 """ 重点:data,status,headers """
视图组件介绍及两个视图基类
# drf视图类 # 1.APIVIew跟之前View区别 - 传入到视图方法中的是REST framework和Request对象,而不是Django的HttpRequest对象: - 视图方法可以返回 REST framework的Response对象 - 任何APIException异常都会被捕获到,并且处理成合适的响应信息; - 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制 # 2.两个视图基类 - APIView -类属性: renderer_classes # 响应格式 parser_classes #能够解析的请求格式 authentication_classes #认证类 throttle_classes #频率类 permission_classes #权限类 -基于APIView+ModelSerializer+Resposne写5个接口 详见代码 # 3.视图类 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': '删除成功'}) # 4.序列化类 ### 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}, } # 5.路由 urlpatterns = [ path('admin/', admin.site.urls), path('books/', views.BookView.as_view()), path('books/<int:pk>/', views.BookDetailView.as_view()), ]
基于GenericAPIView+5个视图扩展类
# 1.视图类 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) # 2.序列化类 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}, } # 3.路由 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}, }
标签:ser,return,仙界,05,self,request,视图,data,drf From: https://www.cnblogs.com/juzijunjun/p/17093871.html