drf入门之反序列化校验源码解析、drf请求、drf响应、视图组件介绍、两个视图基类及五个视图扩展类
1|0drf入门之反序列化校验源码解析、drf请求、drf响应、视图组件介绍、两个视图基类及五个视图扩展类
目录
1|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序列化类的对象 1.切记一定不要按住ctrl键点击 2.真正的执行顺序是,从下往上找,找不到,再往上 3.最终从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
1|2断言(assert)
# 源码中大量使用try和断言 # 关键字assert ,作用:断定你是xx,如果不是就抛异常 name = 'lqz' 正常代码: if name == 'lqz': print('对了') else: print('错了') raise Exception('名字不为lqz,不能继续走了') 断言代码: assert name=='lqz' # 断定是,如果不是,就抛异常 print('后续代码')
1|3drf之请求
- 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
1|4drf之响应
- 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
1|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+Response写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()), ]
1|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()), ]
__EOF__

本文作者:知了了了了
本文链接:https://www.cnblogs.com/zhiliaowang/p/17095804.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/zhiliaowang/p/17095804.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律