测试开发进阶(二十六)

来呀~

欢迎关注我的公众号「测试游记」

序列化器

  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属性「校验的错误提示(字典)」

try:	
    serializer.is_valid(raise_exception=True)	
except Exception as e:	
    return JsonResponse(serializer.errors)

在序列化器中增加 validators

from rest_framework.validators import UniqueValidator	
from projects.models import Projects	
name = serializers.CharField(	
        label='项目名称',	
        max_length=200,	
        help_text='项目名称',	
        validators=[	
            UniqueValidator(	
                queryset=Projects.objects.all(),	
                message='项目名不能重复'	
            )	
        ]	
    )

编写一份创建项目的json640?wx_fmt=jpeg

发送一个创建请求

$ http POST :8000/project/ < projects.json	
zhongxindeMacBook-Pro:apitest zhongxin$ http POST :8000/project/ < projects.json	
HTTP/1.1 200 OK	
Content-Length: 56	
Content-Type: application/json	
Date: Wed, 16 Oct 2019 12:34:16 GMT	
Server: WSGIServer/0.2 CPython/3.7.1	
Vary: Origin	
X-Frame-Options: SAMEORIGIN	
{	
    "name": [	
        "项目名不能重复"	
    ]	
}

640?wx_fmt=jpeg

自定义校验

自己编写一个校验器

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

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

640?wx_fmt=jpeg

单字段校验

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

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

640?wx_fmt=jpeg

修改 projects.json

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

640?wx_fmt=jpeg

多字段校验

def validate(self, attrs):	
    pass

640?wx_fmt=jpeg

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

修改后再次测试

def validate_name(self, value):	
    if not value.endswith('项目'):	
        raise serializers.ValidationError('项目名称必须以「项目」结尾')	
    else:	
        return value

640?wx_fmt=jpeg

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

640?wx_fmt=jpeg

修改 projects.json

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

640?wx_fmt=jpeg

校验器的顺序

  1. 字段定义时的限制,包含 validators列表条目从左到右进行校验

  2. 单字段「 validate_字段名」的校验

  3. 多字段联合校验「 validate方法」

优化视图内代码

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

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

序列化器类 ProjectSerializer中增加 createupdate

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请求

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)

改为

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请求

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)

改为

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)

优化序列化器

from rest_framework import serializers	
class ProjectModelSerializer(serializers.ModelSerializer):	
    class Meta:	
        # 指定参考哪一个模型类来创建	
        model = Projects	
        # 指定为模型类的哪些字段,来生成序列化器	
        fields = '__all__'
In[2]:from projects import serializer	
In[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'})

640?wx_fmt=jpeg

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字段

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增加其他内容

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

测试一下:

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'})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值