Django- REST framework(七)

一、反序列化

  • 数据校验

    • 在定义序列化器时,通过validators选项添加校验器

唯一性约束:UniqueValidator(queryset,message),参数queryset指定查询集,参数message指定校验失败返回的提示信息

class ProjectsSerializer(serializers.Serializer):
  """
  创建项目序列化器类
  """
  #1、label相当于verbose_name,help_text
  #2、需要输出哪些字段,那么在序列化器中就定义哪些字段
  #3、read_only=True指定该字段只能序列化输出
  id = serializers.IntegerField(label='ID', read_only=True)
  name = serializers.CharField(label='项目名称',
                               max_length=200,
                               help_text='项目名称',
                               write_only=True,
                               validators=[UniqueValidator(queryset=Projects.objects.all(), message='不是唯一')])
  leader = serializers.CharField(label='负责人', max_length=50, help_text='负责人')
  tester = serializers.CharField(label='测试人员', max_length=50, help_text='测试人员')
  programer = serializers.CharField(label='开发人员', max_length=50,  help_text='开发人员')
  pubish_app = serializers.CharField(label='发布应用', max_length=100, help_text='发布应用')
   #allow_null相当于模型类中的null,allow_blank相当于模型类中的blank
  desc = serializers.CharField(label='简要描述',  help_text='简要描述', allow_blank=True, default='', allow_null=True)
    • 自定义校验器

#创建自定义校验器
def is_unique_project_name(name):
  if '项目' not in name:
    raise serializers.ValidationError(detail='项目名称中必须包含"项目')
class ProjectsSerializer(serializers.Serializer):
  """
  创建项目序列化器类
  """
  #1、label相当于verbose_name,help_text
  #2、需要输出哪些字段,那么在序列化器中就定义哪些字段
  #3、read_only=True指定该字段只能序列化输出
  id = serializers.IntegerField(label='ID', read_only=True)
  name = serializers.CharField(label='项目名称',
                               max_length=200,
                               help_text='项目名称',
                               write_only=True,
                               validators=[UniqueValidator(queryset=Projects.objects.all(), message='不是唯一'),
                                           is_unique_project_name])
    • 单字段校验(validate_字段名)

  def validate_name(self, value):
    if value.endwith('项目'):
      raise serializers.ValidationError('项目名称必须以"项目"结尾')
    return value

  在序列化定义器类的内部定义的方法,序列化器会自动识别此方法校验字段。

  当校验成功后一定要返回value

    • 多字段联合校验

  #多字段联合校验
  def validate(self, attrs):
    if 'icon' not in attrs['tester'] or 'icon' not in attrs['leader']:
      raise serializers.ValidationError('icon至少是项目负责人或项目测试人员')
    return attrs
  •  校验顺序:

  字段定义时的限制(包含validators列表条目从左到右进行校验) -> 单字段的校验(validate_字段名)->多字段联合校验

二、序列化器-Serializer类

Serializer类自带create,update方法,为对象创建及数据更新提供了直接的方法,那么在views.py中对象创建及数据更新可以进一步优化
  • create
  如果在创建序列化器对象时,只给data传参,那么调用save()方法,实际调用的是序列化器的create()方法

  projects/serializer.py,序列化器类:

  def create(self, validated_data):
    return Projects.objects.create(**validated_data)

  优化projects/views.py中创建对象:

  def post(self, request):
    """新增项目"""
    #1、从前端获取json格式数据,转化为python中的类型(反序列化)

    json_data = request.body.decode('utf-8')
    python_data = json.loads(json_data, encoding='utf-8')
    serializer = ProjectsSerializer(data=python_data)
    #调用序列化对象的is_valid方法,开始校验前端数据
    #校验成功则返回True,否则返回False
    #raise_exception=True,那么校验失败会抛出异常
    try:
      serializer.is_valid(raise_exception=True)
    except Exception as e:
      return JsonResponse(serializer.errors)
    #当调用is_valid方法之后才可以调用errors属性,获取校验的错误提示
    # 校验成功之后的数据,可以使用validated_data来获取
    #3、向数据库新增项目
    # project = Projects.objects.create(**serializer.validated_data)
 
    #1、如果在创建序列化器对象时,只给data传参,那么调用save()方法,实际调用的是序列化器的create()方法
    serializer.save()
    return JsonResponse(serializer.data, status=201)

 

  • update

  如果在创建序列化器对象时,只给data传参,那么调用save()方法,实际调用的是序列化器的create()方法

  projects/serializer.py,序列化器类: 

  def update(self, instance, validated_data):
    instance.name = validated_data['name']
    instance.leader = validated_data['leader']
    instance.tester = validated_data['tester']
    instance.programer = validated_data['programer']
    instance.pubish_app = validated_data['pubish_app']
    instance.desc = validated_data['desc']
    instance.save()
    return instance

  优化projects/views.py中更新数据库:

  def put(self, request, pk):
  
    project = self.get_object(pk)
    #反序列化
    json_data = request.body.decode('utf-8')
    python_data = json.loads(json_data, encoding='utf-8')
    serializer = ProjectsSerializer(instance=project, data=python_data)
    try:
      serializer.is_valid(raise_exception=True)
    except Exception as e:
      return JsonResponse(serializer.errors)
    # #4、更新项目
    # project.name = python_data['name']
    # project.leader = python_data['leader']
    # project.tester = python_data['tester']
    # project.programer = python_data['programer']
    # project.pubish_app = python_data['pubish_app']
    # project.desc = python_data['desc']
    # project.save()
    #在创建序列化器对象时,如果同时给instance和data传参,那么调用save()方法时,实际调用的是序列化器的update()方法
    serializer.save()
    #5、将模型类对象转换成python中的类型
    return JsonResponse(serializer.data, status=201)

三、ModelSerializer

  • 简化序列化器定义
  • 功能
    • 基于模型类自动生成一系列字段
    • 基于模型类自动为Serializer生成validators
    • 包含默认的create()和update()的实现
class ProjectsModelSerializer(ModelSerializer):
  #单字段的校验参照ProjectsSerializer中的定义,不能再Meta子类中定义
  class Meta:
    #1、指定参考哪一个模型类来创建
    model = Projects
    #2、指定模型类的那些字段来生成序列化器
    #字段生成的方法:
    fields = "__all__"#全字段
    fields = ("id", "name", "leader", "tester", "programer")#指定字段
    exclude = ("pubish_app", "desc")#指定字段,生成的字段是元组内除外的字段
    #指定字段的属性:read_only = 'True'
    read_only_fields = ('leader', 'tester')
    #模型类字段修改
    extra_kwargs = {
      'leader': {
        'write_only': True,
        'error_messages': {'max_length': '最大长度不超过50'}
      }
    }

四、参数总结

  • 选项参数

  max_length     最大长度

  min_length      最小长度

  allow_blank     是否允许为空

  trim_whitesspaces   是否截断空白字符

  max_value      最小值

  min_value       最大值

  • 通用参数

  read_only         表明该字段仅用于序列化输出,默认False

  write_only        表明该字段仅用于反序列化输入,默认False

  required          表明该字段在反序列化时必须输入,默认True

  default            反序列化时使用的默认值

  allow_null         表明该字段是否允许传入None,默认False

  validators        该字段使用校验器

  error_messages  包含错误编号与错误信息的字典

  label              用于html展示API页面时,显示的字段名称

  help_text       用于html展示API页面时,显示的字段帮助提示信息

五、关联字段序列化

  • 子表中关联字段序列化
    • PrimaryKeyRelatedField   
      数据库模型中的外键字段,默认会生成PrimaryKeyRelatedField序列化字段,序列化输出的为外键ID值

    

    • StringRelatedField  
      此字段将被序列化为关联对象字符串表达形式(即__str__方法返回值)
    • SlugRelatedField
      此字段将被序列化为关联对象的指定字段数据
    • 使用关联对象的序列化器
from rest_framework import serializers
from interfaces.models import Interfaces
from projects.serializer import ProjectsModelSerializer
class InterfacesModelSerializers(serializers.ModelSerializer):
  # 1、数据库模型中的外键字段,默认会生成PrimaryKeyRelatedField序列化字段
  # 2、序列化输出的值为外键的ID值
  # 3、StringRelatedField,此字段将被序列化为关联对象字符串表达形式(即__str__方法返回值)
  # project = serializers.StringRelatedField(label="所属项目", slug_field='tester')
  # 4、StringRelatedField,此字段将被序列化为关联对象的指定字段数据
  # project = serializers.SlugRelatedField(slug_field='tester') 
# 5、使用关联对象的序列化器 project = ProjectsModelSerializer(label='所属项目', read_only=True ) class Meta: model = Interfaces fields = "__all__"
  • 父表中关联字段序列化
 #父表中默认不会生成关联字段(从表),可以手动指定,字段名默认为:子表模型类名小写_set
  interfaces_set = serializers.StringRelatedField(many=True)

六、痛点

  • requset请求只接收json数据
  • 返回数据只有json格式

7、Request

  • 对Django中的HttpRequesr进行了拓展
    • 会根据请求头中的Content-Type,自动进行解析  
    • 无论前端发送那种格式的数据,都可以以相同的方式读取
  • request.data
    • 类似于Django中的request.POST和request.FILES
    • 可以对POST、PUT、PATCH的请求体参数进行解析
    • 不仅支持form传参,也支持json格式传参
  • request.query_params
    • 类似于Django中的request.GET
    • 获取查询字符串参数
  • 支持Django HTTPRequest中的所有的对象和方法

8、Response

  • 对Django中的HttpResponse进行了拓展
    • 会根据请求头中的Accept,自动转化响应数据到对应格式
  • 如果请求头中未设置Accept,则会蚕蛹默认方式处理响应数据(默认返回json格式)
  • 指定响应默认渲染类

在全局配置文件中setting.py

#DRF框架所有的全局配置都放在REST_FRAMEWORK这个字典中
REST_FRAMEWORK = {
    #默认响应渲染类
    'DEFAULT_RENDERER_CLASSES': (
    #json渲染器为第一优先级
    'rest_framework.renderers.JSONRenderer',
    #可浏览的API渲染器为第二优先级
    'rest_framework.renderers.BrowsableAPIRenderer',
    )
}
  • Response(data, status=None, template_name=None, headers=None, content_type=None)
  • 参数说明
    • data 
      • 序列化处理后的数据
      • 一般为serializer.data(python基本数据类型,嵌套字典的列表)
    • status
      • 状态码,默认200
    • template_name
      • 模板名称,使用HTMLRenderer渲染时需指明  
    • headers
      • 用于存放响应头信息的字典 
    • content_type
      • 响应头中的Content_type
      • 通常此参数无需设置,会自动根据前端所需类型来设置该参数    
 def post(self, request):
    """新增项目"""
    
    #当视图继承APIView之后,请求方法实例第二个参数为Request对象,是对django中HTTPRequest对象的扩展
    serializer = ProjectsSerializer(data=request.data)
    #调用序列化对象的is_valid方法,开始校验前端数据
    #校验成功则返回True,否则返回False
    #raise_exception=True,那么校验失败会抛出异常
    try:
      serializer.is_valid(raise_exception=True)
    except Exception as e:
      return Response(serializer.errors)
    #当调用is_valid方法之后才可以调用errors属性,获取校验的错误提示
    # 校验成功之后的数据,可以使用validated_data来获取
    #1、如果在创建序列化器对象时,只给data传参,那么调用save()方法,实际调用的是序列化器的create()方法
    serializer.save()
    return Response(serializer.data, status=status.HTTP_201_CREATED)

 

posted @ 2019-10-20 04:43  sinder2018  阅读(65)  评论(0)    收藏  举报