前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >测试开发进阶(二十六)

测试开发进阶(二十六)

作者头像
zx钟
发布2019-10-17 17:29:10
4330
发布2019-10-17 17:29:10
举报
文章被收录于专栏:测试游记测试游记

序列化器

  1. 序列化器中定义的类属性字段,往往与模型类字段一一对应
  2. label选项相当于 verbose_name;
  3. 定义的序列化器字段,默认既可以进行序列化输出,也可以进行反序列化输入

通用参数

  • read_only=True 指定该字段只能进行序列化输出
  • write_only=True 指定该字段只进行反序列化输入,但不进行序列化输出
  • required该字段在反序列化时必须传入,默认为True
  • default反序列化时使用的默认值
  • allow_null该字段是否允许传入None,默认False
  • validators该字段使用的校验器
  • error_messages包含错误key与错误信息的字典(下面有例子)
  • label用于HTML展示API页面时,显示的字段名称

选项参数

  • max_length最大长度
  • min_length最小长度
  • allow_blank是否允许为空
  • trim_whitespace是否截断空白字符
  • max_value最小值
  • min_value最大值

校验

  1. 调用序列化器对象的 is_valid方法,才开始校验前端参数
  2. 如果校验成功,则返回 True,校验失败返回 False
  3. raise_exception=True,校验失败后会抛出异常
  4. 当调用 is_valid方法之后,才可以调用 errors属性「校验的错误提示(字典)」
代码语言:javascript
复制
try:    serializer.is_valid(raise_exception=True)except Exception as e:    return JsonResponse(serializer.errors)

在序列化器中增加 validators

代码语言:javascript
复制
from rest_framework.validators import UniqueValidatorfrom projects.models import Projectsname = serializers.CharField(        label='项目名称',        max_length=200,        help_text='项目名称',        validators=[            UniqueValidator(                queryset=Projects.objects.all(),                message='项目名不能重复'            )        ]    )

编写一份创建项目的json

发送一个创建请求

代码语言:javascript
复制
$ http POST :8000/project/ < projects.jsonzhongxindeMacBook-Pro:apitest zhongxin$ http POST :8000/project/ < projects.jsonHTTP/1.1 200 OKContent-Length: 56Content-Type: application/jsonDate: Wed, 16 Oct 2019 12:34:16 GMTServer: WSGIServer/0.2 CPython/3.7.1Vary: OriginX-Frame-Options: SAMEORIGIN{    "name": [        "项目名不能重复"    ]}

自定义校验

自己编写一个校验器

需求:项目名称中必须包含 项目关键字

代码语言:javascript
复制
def is_unique_project_name(name):    """    项目名称中需要包含「项目」关键字    :param name:前端传递给我的项目名称    :return:    """    if '项目' not in name:        raise serializers.ValidationError(detail='项目名称中必须包含「项目」')
代码语言:javascript
复制
name = serializers.CharField(    label='项目名称',    max_length=200,    help_text='项目名称',    validators=[        UniqueValidator(            queryset=Projects.objects.all(),            message='项目名不能重复'        ), is_unique_project_name    ])

单字段校验

在序列化器内部增加 defvalidate_name(self,value):

代码语言:javascript
复制
# 单字段的校验def validate_name(self, value):    if value.endswith('项目'):        raise serializers.ValidationError('项目名称必须以「项目」结尾')
代码语言:javascript
复制
# projects.json{  "name": "测试游记1",  "leader": "zhongxin",  "tester": "zhongxin",  "programer": "zhong3",  "publish_app": "公众号",  "desc": "无"}

修改 projects.json

代码语言:javascript
复制
# projects.json{  "name": "测试游记项目1",  "leader": "zhongxin",  "tester": "zhongxin",  "programer": "zhong3",  "publish_app": "公众号",  "desc": "无"}

多字段校验

代码语言:javascript
复制
def validate(self, attrs):    pass

这里 nameNone是因为上面单字段校验没有返回value

修改后再次测试

代码语言:javascript
复制
def validate_name(self, value):    if not value.endswith('项目'):        raise serializers.ValidationError('项目名称必须以「项目」结尾')    else:        return value
代码语言:javascript
复制
def validate(self, attrs):    """    多字段联合校验    需求:tester和leader中有「icon」    :param attrs:    :return:    """    if 'icon' not in attrs['tester'] and 'icon' not in attrs['leader']:        raise serializers.ValidationError('「icon」必须是项目负责人或者在项目的测试人员')    else:        return attrs

修改 projects.json

代码语言:javascript
复制
# projects.json{  "name": "测试游记项目",  "leader": "icon",  "tester": "zhongxin",  "programer": "zhong3",  "publish_app": "公众号",  "desc": "无"}

校验器的顺序

  1. 字段定义时的限制,包含 validators列表条目从左到右进行校验
  2. 单字段「 validate_字段名」的校验
  3. 多字段联合校验「 validate方法」

优化视图内代码

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

序列化器类 ProjectSerializer中增加 createupdate

代码语言:javascript
复制
def create(self, validated_data):    return Projects.objects.create(**validated_data)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.publish_app = validated_data['publish_app']    instance.desc = validated_data['desc']    instance.save()    return instance

修改post请求

代码语言:javascript
复制
def post(self, request):    """    新建项目    """    json_data = request.body.decode('utf8')    python_data = json.loads(json_data, encoding='utf8')    serializer = ProjectSerializer(data=python_data)    try:        serializer.is_valid(raise_exception=True)    except Exception as e:        return JsonResponse(serializer.errors)    project = Projects.objects.create(**serializer.validated_data)    serializer = ProjectSerializer(instance=project)    return JsonResponse(serializer.data, status=201)

改为

代码语言:javascript
复制
def post(self, request):    """    新建项目    """    json_data = request.body.decode('utf8')    python_data = json.loads(json_data, encoding='utf8')    serializer = ProjectSerializer(data=python_data)    try:        serializer.is_valid(raise_exception=True)    except Exception as e:        return JsonResponse(serializer.errors)    serializer.save()    return JsonResponse(serializer.data, status=201)

修改put请求

代码语言:javascript
复制
def put(self, request, pk):    project = self.get_object(pk)    json_data = request.body.decode('utf8')    python_data = json.loads(json_data, encoding='utf8')    serializer = ProjectSerializer(data=python_data)    try:        serializer.is_valid(raise_exception=True)    except Exception as e:        return JsonResponse(serializer.errors)    project.name = serializer.validated_data['name']    project.leader = serializer.validated_data['leader']    project.tester = serializer.validated_data['tester']    project.programer = serializer.validated_data['programer']    project.publish_app = serializer.validated_data['publish_app']    project.desc = serializer.validated_data['desc']    project.save()    serializer = ProjectSerializer(instance=project)    return JsonResponse(serializer.data, status=201)

改为

代码语言:javascript
复制
def put(self, request, pk):    project = self.get_object(pk)    json_data = request.body.decode('utf8')    python_data = json.loads(json_data, encoding='utf8')    serializer = ProjectSerializer(instance=project, data=python_data)    try:        serializer.is_valid(raise_exception=True)    except Exception as e:        return JsonResponse(serializer.errors)    serializer.save()    return JsonResponse(serializer.data, status=201)

优化序列化器

代码语言:javascript
复制
from rest_framework import serializersclass ProjectModelSerializer(serializers.ModelSerializer):    class Meta:        # 指定参考哪一个模型类来创建        model = Projects        # 指定为模型类的哪些字段,来生成序列化器        fields = '__all__'
代码语言:javascript
复制
In[2]:from projects import serializerIn[3]:serializer.ProjectModelSerializer()Out[3]: ProjectModelSerializer():    id = IntegerField(label='ID', read_only=True)    name = CharField(help_text='项目名称', label='项目名称', max_length=200, validators=[<UniqueValidator(queryset=Projects.objects.all())>])    leader = CharField(help_text='负责人', label='负责人', max_length=50)    tester = CharField(help_text='测试人员', label='测试人员', max_length=50)    programer = CharField(help_text='开发人员', label='开发人员', max_length=50)    publish_app = CharField(help_text='发布应用', label='发布应用', max_length=50)    desc = CharField(allow_blank=True, allow_null=True, help_text='简要描述', label='简要描述', required=False, style={'base_template': 'textarea.html'})
代码语言:javascript
复制
fields = ('id', 'name', 'leader', 'tester', 'programer', 'publish_app')exclude = ('publish_app')read_only_fields = ('leader','tester')
  • fields:指定显示哪些 exclude:指定排除哪些 read_only_fields:指定 read_only=True的字段

如果需要修改 name的校验,自定义一个 name字段

代码语言:javascript
复制
class ProjectModelSerializer(serializers.ModelSerializer):    name = serializers.CharField(        label='项目名称',        max_length=200,        help_text='项目名称',        validators=[            UniqueValidator(                queryset=Projects.objects.all(),                message='项目名不能重复'            ), is_unique_project_name        ],        error_messages={'max_length': '长度不能超过200个字节'}    )    class Meta:        model = Projects        fields = '__all__'        read_only_fields = ('leader', 'tester')

也可以增加 extra_kwargs增加其他内容

代码语言:javascript
复制
class Meta:    # 指定参考哪一个模型类来创建    model = Projects    # 指定为模型类的哪些字段,来生成序列化器    fields = '__all__'    extra_kwargs = {        'leader': {            'write_only': True,            'error_messages': {'max_length': '长度不能超过50个字节'}        }    }

测试一下:

代码语言:javascript
复制
Out[3]: ProjectModelSerializer():    id = IntegerField(label='ID', read_only=True)    name = CharField(error_messages={'max_length': '长度不能超过200个字节'}, help_text='项目名称', label='项目名称', max_length=200, validators=[<UniqueValidator(queryset=<QuerySet [<Projects: 测试游记>, <Projects: 测试游记1>, <Projects: 「测试游记」-创建>, <Projects: 1015项目>, <Projects: 测试游记项目>]>)>, <function is_unique_project_name>])    leader = CharField(error_messages={'max_length': '长度不能超过50个字节'}, help_text='负责人', label='负责人', max_length=50, write_only=True)    tester = CharField(help_text='测试人员', label='测试人员', max_length=50)    programer = CharField(help_text='开发人员', label='开发人员', max_length=50)    publish_app = CharField(help_text='发布应用', label='发布应用', max_length=50)    desc = CharField(allow_blank=True, allow_null=True, help_text='简要描述', label='简要描述', required=False, style={'base_template': 'textarea.html'})
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试游记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 序列化器
    • 通用参数
      • 选项参数
      • 校验
        • 自定义校验
          • 单字段校验
            • 多字段校验
              • 校验器的顺序
              • 优化视图内代码
                • 修改post请求
                  • 修改put请求
                  • 优化序列化器
                  相关产品与服务
                  文件存储
                  文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档