1.内部类
就是当前类的配置类
1.序列化组件的配置类
2.数据库model配置类
解释: 伪代码 继承的model类支持db_name,所以Meta类要使用db_name的写法
""" class Car(Model): name = CharFields() class Meta: db_name = "表名" # Car表,将会name作为Car表的字段 (内部可以通过Car.name访问到name) (内部可以通过Car.Meta.db_name访问到 "表名" => table的表名) if Car.Meta.db_name: table的表名 = Car.Meta.db_name else: table的表名 = Car.__class__.name """
2.响应类分析 reponse
1.reponse类源码分析
响应类Response源码 def __init__(self, data=None, status=None, template_name=None, headers=None, exception=False, content_type=None): pass data:响应的数据 - 空、字符串、数字、列表、字段、布尔 status:网络状态码 template_name:drf说自己也可以支持前后台不分离返回页面,但是不能和data共存(不会涉及) headers:响应头(不用刻意去管) exception:是否是异常响应(如果是异常响应,可以赋值True,没什么用) content_type:响应的结果类型(如果是响应data,默认就是application/json,所有不用管)
2.运用
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status #网络状态码模块 可以进去看源码 from . import models, serializers class UserAPIView(APIView): def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: # 单查 # 1)数据库交互拿到资源obj或资源objs # 2)数据序列化成可以返回给前台的json数据 # 3)将json数据返回给前台 try: obj = models.User.objects.get(pk=pk) serializer = serializers.UserModelSerializer(obj, many=False) return Response({ 'status': 0, 'msg': 'ok', 'result': serializer.data }) except: return Response( data={ 'status': 1, 'msg': 'pk error' }, status=status.HTTP_400_BAD_REQUEST, # 比直接写400更具有描述性 exception=True )
3.序列化参数分析
1.源码分析
序列化类BaseSerializer def __init__(self, instance=None, data=empty, **kwargs): pass instance:是要被赋值对象的 - 对象类型数据赋值给instance data:是要被赋值数据的 - 请求来的数据赋值给data kwargs:内部有三个属性:many、partial、context many:操作的对象或数据,是单个的还是多个的 partial: context: 下面两个参数后期会讲
2.运用 序列化实现单查 群查
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from . import models, serializers class UserAPIView(APIView): def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: # 单查 # 1)数据库交互拿到资源obj或资源objs # 2)数据序列化成可以返回给前台的json数据 # 3)将json数据返回给前台 try: obj = models.User.objects.get(pk=pk) serializer = serializers.UserModelSerializer(obj, many=False) instance return Response({ 'status': 0, 'msg': 'ok', 'result': serializer.data }) except: return Response( data={ 'status': 1, 'msg': 'pk error' }, status=status.HTTP_400_BAD_REQUEST, # 比直接写400更具有描述性 exception=True ) else: # 群查 # 1)数据库交互拿到资源obj或资源objs # 2)数据序列化成可以返回给前台的json数据 # 3)将json数据返回给前台 queryset = models.User.objects.all() serializer = serializers.UserModelSerializer(queryset, many=True) return Response({ 'status': 0, 'msg': 'ok', 'results': serializer.data }) def post(self, request, *args, **kwargs): # 单增 # 1)从请求request中获得前台提交的数据 # 2)将数据转换成Model对象,并完成数据库入库操作(序列化组件完成) # 3)将入库成功的对象列化成可以返回给前台的json数据(请求与响应数据不对等:请求需要提交密码,响应一定不展示密码) # 4)将json数据返回给前台 # 1)将前台请求的数据交给序列化类处理 # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续 # 3)序列化组件完成数据入库操作,得到入库对象 # 4)响应结果给前台 serializer = serializers.UserModelSerializer(data=request.data) if serializer.is_valid(): # 校验成功 => 入库 => 正常响应 obj = serializer.save() return Response({ 'status': 0, 'msg': 'ok', 'result': '新增的那个对象' }, status=status.HTTP_201_CREATED) else: # 校验失败 => 异常响应 return Response({ 'status': 1, 'msg': serializer.errors, }, status=status.HTTP_400_BAD_REQUEST)
4.反序列化实现单增
1.数据校验: serializer.is_valid():
2.数据保存:obj = serializer.save()
3.错误信息:serializer.errors
def post(self, request, *args, **kwargs): # 单增 # 1)从请求request中获得前台提交的数据 # 2)将数据转换成Model对象,并完成数据库入库操作(序列化组件完成) # 3)将入库成功的对象列化成可以返回给前台的json数据(请求与响应数据不对等:请求需要提交密码,响应一定不展示密码) # 4)将json数据返回给前台 # 1)将前台请求的数据交给序列化类处理 # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续 # 3)序列化组件完成数据入库操作,得到入库对象 # 4)响应结果给前台 serializer = serializers.UserModelSerializer(data=request.data) if serializer.is_valid(): # 校验成功 => 入库 => 正常响应 obj = serializer.save() return Response({ 'status': 0, 'msg': 'ok', 'result': '新增的那个对象' }, status=status.HTTP_201_CREATED) else: # 校验失败 => 异常响应 return Response({ 'status': 1, 'msg': serializer.errors, }, status=status.HTTP_400_BAD_REQUEST)
5.基础校验规则
后面练习多体会
from rest_framework import serializers from rest_framework import exceptions from . import models class UserModelSerializer(serializers.ModelSerializer): # 自定义反序列化字段(所有校验规则自己定义,也可以覆盖model已有的字段) # 覆盖model有的字段,不明确write_only会参与序列化过程 password = serializers.CharField(min_length=4, max_length=8, write_only=True) # 自定义字段,不明确write_only序列化会报错,序列化会从model中强行反射自定义字段,但是model没有对于字段 re_password = serializers.CharField(min_length=4, max_length=8, write_only=True) class Meta: # 该序列化类是辅助于那个Model类的 model = models.User # 设置参与序列化与反序列化字段 # 插拔式:可以选择性返回给前台字段(插头都是在Model类中制造) # fields = ['name', 'age', 'height', 'sex', 'icon] # 第一波分析: # 1)name和age,在fields中标明了,且没有默认值,也不能为空,入库时必须提供,所有校验时必须提供 # 2)height,在fields中标明了,但是有默认值,所有前台不提供,也能在入库时采用默认值(可以为空的字段同理) # 3)password,没有在fields中标明了,所以校验规则无法检测password情况,但是即使数据校验提供了, # 也不能完成入库,原因是password是入库的必填字段 # 4)gender和img是自定义插拔@property字段,默认就不会进行校验(不参与校验) # fields = ['name', 'age', 'height', 'gender', 'img'] # 第二波分析: # 1)如何区分 序列化反序列化字段 | 只序列化字段(后台到前台) | 只反序列化字段(前台到后台) # 不做write_only和read_only任何限制 => 序列化反序列化字段 # 只做read_only限制 => 只序列化字段(后台到前台) # 只做write_only限制 => 只反序列化字段(前台到后台) # 2)对前台到后台的数据,制定基础的校验规则(了解) # CharField(max_length, min_length, errors_kwargs) # DecimalField(min_value, max_value, max_digits, decimal_places,error_messages) # 3)如果一个字段有默认值或是可以为空,比如height,如何做限制 # 虽然有默认值或是可以为空,能不能强制限制必须提供,可以通过required是True来限制 # 前台提交了该字段,我就校验,没提交我就不校验:1)required是False 2)有校验规则 fields = ['name', 'age', 'password', 'height', 'gender', 'img', 're_password'] # 第三波分析 # 1)制定的简易校验规则(没有制定)后,可以再通过字段的 局部钩子 对该字段进行复杂校验 # 2)每个字段进行逐一复杂校验后,还可以进行集体的 全局钩子 校验 # 涉及对自定义反序列化字段的校验:re_password(要参与校验,但是不会入库) # 校验规则 extra_kwargs = { 'name': { # 'write_only': True, # 'read_only': True }, 'password': { 'write_only': True, 'min_length': 3, 'max_length': 8, 'error_messages': { # 可以被国际化配置替代 'min_length': '太短', 'max_length': '太长' } }, 'height': { # 'required': True, 'min_value': 0, } }
6.自定义校验规则 全局钩子 局部钩子
from rest_framework import serializers from rest_framework import exceptions from . import models class UserModelSerializer(serializers.ModelSerializer): # 自定义反序列化字段(所有校验规则自己定义,也可以覆盖model已有的字段) # 覆盖model有的字段,不明确write_only会参与序列化过程 password = serializers.CharField(min_length=4, max_length=8, write_only=True) # 自定义字段,不明确write_only序列化会报错,序列化会从model中强行反射自定义字段,但是model没有对于字段 re_password = serializers.CharField(min_length=4, max_length=8, write_only=True)
fields = ['name', 'age', 'password', 'height', 'gender', 'img', 're_password']
# 注:局部全局钩子,是和Meta同缩减,属于序列化类的 # 局部钩子:validate_要校验的字段(self, 要校验的字段值) # 全局钩子:validate(self, 所以字段值的字典) # 校验规则:成功返回传来的数据 | 失败抛出异常 def validate_name(self, value): if 'g' in value.lower(): raise exceptions.ValidationError("这个g不行") else: return value def validate(self, attrs): print(attrs) password = attrs.get('password') # 只是拿出来校验 re_password = attrs.pop('re_password') # 必须取出校验,因为不能入库 if password != re_password: raise exceptions.ValidationError({'re_password': '两次密码不一致'}) else: return attrs
数据写入
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from . import models, serializers
def post(self, request, *args, **kwargs): # 单增 # 1)从请求request中获得前台提交的数据 # 2)将数据转换成Model对象,并完成数据库入库操作(序列化组件完成) # 3)将入库成功的对象列化成可以返回给前台的json数据(请求与响应数据不对等:请求需要提交密码,响应一定不展示密码) # 4)将json数据返回给前台 # 1)将前台请求的数据交给序列化类处理 # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续 # 3)序列化组件完成数据入库操作,得到入库对象 # 4)响应结果给前台 serializer = serializers.UserModelSerializer(data=request.data) if serializer.is_valid(): # 校验成功 => 入库 => 正常响应 obj = serializer.save() return Response({ 'status': 0, 'msg': 'ok', 'result': '新增的那个对象' }, status=status.HTTP_201_CREATED) else: # 校验失败 => 异常响应 return Response({ 'status': 1, 'msg': serializer.errors, }, status=status.HTTP_400_BAD_REQUEST)