解析模块、异常模块、响应模块、序列化组件:Serializer(偏底层)
解析模块 parsers
源码入口 setting
全局解析类配置
# 解析类全局配置 'DEFAULT_PARSER_CLASSES': [ 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser']
# 局部解析类配置
# 局部解析配置 from rest_framework.parsers import JSONParser class Book(APIView): parser_classes = [JSONParser] def get(self, request, *args, **kwargs): return Response('get ok')
异常模块 exception
为什么要自定义异常:
1.所有经过drf的Apivview视图类产生的异常,都可以提供异常处理方案
2.drf默认提供异常处理方案(rest_framework.views.exception_handler),但是处理范围有限
3.drf提供的处理方案两种,处理了返回异常信息,没有处理返回none(接着就是服务器抛异常给前台)
4.自定义异常的目标就是没有处理的异常,让前台得到合理的异常信息返回,后台记录异常具体信息
源码入口:response = self.handle_exception(exc)
自定义异常:
1.先在settings配置REST_FRAMEWORK = { # 全局异常模块配置 'EXCEPTION_HANDLER': 'api.exception.exception_handler', } 2.在api项目名中新建exception.py文件夹 3.拦截 response =exception_handler(exc,context),如果不为空,自定义返回内容 from rest_framework.views import exception_handler as drf_exception_handler from rest_framework.response import Response def exception_handler(exc, context): response = drf_exception_handler(exc,context) if response is None: return Response({ "detail":"服务器有毛病" }) return response
响应模块 Response
响应类构造器
def __init__(self, data=None, status=None, template_name=None, headers=None, exception=False, content_type=None): """ :param data: 响应数据 :param status: 响应状态码 :param template_name: drf可以渲染页面,渲染的页面模板地址 :param headers: 响应头 :param exception: 是否异常 :param content_type: 响应的数据格式(一般不用处理,响应中带了,一般是json) """ 常规实例化响应对象 from rest_framework import status return Response(data={数据},status=status.HTTP_200_ok,headers={自定义响应头})
序列化组件:Serializer(偏底层)
\ModelSerializer(重点)\ListModelSerializer(辅助群改)
Serializer:
1.用Serializer主要是后台返回数据给前端时候不能返回对象,如果字段名过多,书写不方便 2.先在api文件夹中建立一个serializers.py文件夹,导入模块 from rest_framework import serializers 3.定义一个Serializer序列化类 # 序列化组件的工作方式与的django froms组件相似 class UserSerializer(serializers.Serializer): # 序列化提供给前台的字段个数由后台决定,可以少提供,但是字段名一定和建表时候一致 name = serializers.CharField() phone = serializers.CharField() sex = serializers.IntegerField() icon = serializers.ImageField() # 自定义序列化属性 # 属性名随意,值由固定的命名规范方法提供:get_属性名(self,参与序列化对象obj),返回自定义属性的值 gender = serializers.SerializerMethodField() def get_gender(self, obj): # choice类型的的正确显示方法get_字段名_display() return obj.get_sex_display() 4.使用Serializer先在视图函数中定义user_ser = serializers.UserSerializer(user_obj),返回user_ser即可
反序列化:
# 反序列化就是接收数据,并进行校验,入库
#1.user_ser = serializers.UserDeserializer(data=request_data)反序列化进行校验内容是否合法 #2.进入反序列化后用局部钩子和全局钩子分别对单个字段进行校验和校验成功新增入库 # 反序列化 class UserDeserializer(serializers.Serializer): # 1.哪些字段必须反序列化 # 2.字段都有哪些安全校验 # 3.哪些字段需要额外提供校验 # 4.哪些字段间存在联合校验 # 注:反序列化都是用来入库,不会出现自定义字段,并且可以设置校验规则自定义属性 name = serializers.CharField( max_length=60, min_length=5, error_messages={ 'max_length': '太长不好', 'min_length': '太短也不行', } ) # 最长和最短不能超过10 psd = serializers.CharField() phone = serializers.CharField(required=False) sex = serializers.IntegerField(required=False) # 自定义需要校验的字段 re_pwd = serializers.CharField(required=True) # 局部钩子: validate_要校验的字段名(self,当前要校验的字段值) # 校验规则:校验通过返回原值,校验失败,抛出异常 def validate_name(self, value): # print("value:",value) if "jb" in value.lower(): raise exceptions.ValidationError("名字非法,有jb字符") return value # 全局钩子 attrs:系统与局部钩子通过的所有数据 attrs就是一个字典,所有通过的数据 def validate(self, attrs): # print('attrs:', attrs) psd = attrs.get("psd") re_pwd = attrs.get("re_pwd") if psd != re_pwd: raise exceptions.ValidationError({"pwd":"密码错误"}) return attrs # 要完成新增,需要自己重写create方法 def create(self, validated_data): # validated_data.pop("re_pwd") # 尽量在所有校验规则完毕之后,数据可以直接入库 return models.User.objects.create(**validated_data) #3.if user_ser.is_valid():是否通过 # 反序列化接收数据入库 def post(self, request, *args, **kwargs): request_data = request.data if not isinstance(request.data, dict) or request_data == {}: # 是否是字典,合法数据类型 return Response({ 'status': 1, 'msg': "数据有误" }) # 数据类型合法之后,但是数据内容不一定合法,需要校验数据 # print(request.data) user_ser = serializers.UserDeserializer(data=request_data) print(user_ser) if user_ser.is_valid(): # 校验通过,完成新增 user_obj = user_ser.save() return Response({ 'status': 0, 'msg': "ok", 'results':serializers.UserSerializer(user_obj).data }) else: return Response({ 'status': 1, 'msg': user_ser.errors })