verbose_name
;read_only=True
指定该字段只能进行序列化输出write_only=True
指定该字段只进行反序列化输入,但不进行序列化输出required
该字段在反序列化时必须传入,默认为Truedefault
反序列化时使用的默认值allow_null
该字段是否允许传入None,默认Falsevalidators
该字段使用的校验器error_messages
包含错误key与错误信息的字典(下面有例子)label
用于HTML展示API页面时,显示的字段名称max_length
最大长度min_length
最小长度allow_blank
是否允许为空trim_whitespace
是否截断空白字符max_value
最小值min_value
最大值is_valid
方法,才开始校验前端参数True
,校验失败返回 False
raise_exception=True
,校验失败后会抛出异常is_valid
方法之后,才可以调用 errors
属性「校验的错误提示(字典)」try: serializer.is_valid(raise_exception=True)except Exception as e: return JsonResponse(serializer.errors)
在序列化器中增加 validators
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
发送一个创建请求
$ 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": [ "项目名不能重复" ]}
自己编写一个校验器
需求:项目名称中必须包含 项目
关键字
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 ])
在序列化器内部增加 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": "无"}
修改 projects.json
# projects.json{ "name": "测试游记项目1", "leader": "zhongxin", "tester": "zhongxin", "programer": "zhong3", "publish_app": "公众号", "desc": "无"}
def validate(self, attrs): pass
这里 name
为 None
是因为上面单字段校验没有返回value
修改后再次测试
def validate_name(self, value): if not value.endswith('项目'): raise serializers.ValidationError('项目名称必须以「项目」结尾') else: return value
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
# projects.json{ "name": "测试游记项目", "leader": "icon", "tester": "zhongxin", "programer": "zhong3", "publish_app": "公众号", "desc": "无"}
validators
列表条目从左到右进行校验validate_字段名
」的校验validate
方法」
如果在创建序列化器对象时候,只给data传参,那么调用save()方法实际调用的就是序列化器对象的 create()
方法
在创建序列化器对象时,同时给instance和data传参,那么调用save()方法实际调用的就是序列化器对象的 update()
方法
序列化器类 ProjectSerializer
中增加 create
和 update
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
从
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)
从
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 serializersclass ProjectModelSerializer(serializers.ModelSerializer): class Meta: # 指定参考哪一个模型类来创建 model = Projects # 指定为模型类的哪些字段,来生成序列化器 fields = '__all__'
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'})
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'})