之前我们使用的是djang的views视图集里自定义序列化输出与反序列化输入,弊端也显而易见,代码比较冗余繁琐,最主要的是 数据校验,非常复杂,比如是否传递数据、是否传递json格式的参数、是否传递合法的参数(参数类型、参数的个数、参数的其他约束),所以接下来要学习使用序列化器进行序列化与反序列化操作。
定义序列化器文件serializers.py
- 定义序列化器类,需要继承Serializer基类或者Serializer的子类
- 定义的序列化器类中的字段名要与模型类中的字段名保持一次
- label和help_text与模型类中的verbose_name和help_text是一致的
- 默认情况下,序列化类中定义了哪些字段,那么哪些字段就会被返回,如果不想返回给前端,那么就直接不定义
- 默认情况下,序列化类中定义了哪些字段,那么哪些字段就一定要输入
- 如果某个字段,指定了read_only=True,那么该字段,只进行序列化输出,不需要输入(反序列化输入)
- 如果某个字段,指定了write_only=True,那么该字段,只进行反序列化输入,不需要输出(序列化输出)
- 设置validators参数,可以为该字段指定约束条件
- validators参数只能为列表或者元组
- 可以使用UniqueValidator来指定唯一约束条件,第一个参数为查询集对象,message关键字参数可以指定具体的报错信息,列表或者元组中的每一个元素,为一个约束条件
- 一个是不传该字段,一个是传空值(空字符串),是不一样的
- allow_blank=True,那么该字段可以传递空字符串“”
- allow_null=True,那么该字段可以传递空值(null)
- 如果设置default参数,那么前端可以不传该字段,会自动使用默认值来传递,同时不会校验
class ProjectSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id主键", help_text="id主键", read_only=True)
name = serializers.CharField(label="接口名称", help_text="接口名称", max_length=10, min_length=5,
validators=[UniqueValidator(ProjectsModel.objects.all(), message="项目名称不可重复!")])
leader = serializers.CharField(label="负责人", help_text="负责人")
tester = serializers.CharField(label="接口测试人员", help_text="接口测试人员", max_length=10, min_length=5,
error_messages={"min_length": "tester长度不能少于5位", "max_length": "tester长度不能大于10位",
"required": "tester字段为必填项"})
desc = serializers.CharField(label="接口描述", help_text="接口描述", allow_null=True, default=" desc默认值")
publish_app = serializers.CharField(label="开发应用", help_text="开发应用", allow_null=True, default=" publish_app默认值")
programmer = serializers.CharField(label="开发人员", help_text="开发人员", allow_null=True, default=" programmer默认值")
改造之前写的views.py文件
class ProjectsDetailViews(View):
def get_object(self, pk):
# 查询指定pk的数据
ret = {
"msg": "传参异常",
"code": 404
}
try:
return ProjectsModel.objects.get(pk=pk)
# 如果入参是不存在的id数据,抛出异常
except Exception:
return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404)
def get(self, request, pk):
pro=self.get_object(pk)
serializer_obj=ProjectSerializer(instance=pro)
return JsonResponse(serializer_obj.data,json_dumps_params={"ensure_ascii": False})
# 更新数据
def put(self, request, pk):
ret = {
"msg": "传参异常",
"code": 404
}
try:
# 查出对应id的数据
query_data = self.get_object(pk)
# 提取传入的参数
data_str = request.body.decode('utf-8')
data_dict = json.loads(data_str)
except Exception:
return JsonResponse(ret, json_dumps_params={"ensure_ascii": False})
serializer_obj = ProjectSerializer(data=data_dict)
if not serializer_obj.is_valid():
ret.update(serializer_obj.errors)
return JsonResponse(ret, json_dumps_params={"ensure_ascii": False})
# 修改老数据,传入新数据给对应字段
query_data.name = serializer_obj.validated_data.get("name")
query_data.leader = serializer_obj.validated_data.get("leader")
query_data.desc = serializer_obj.validated_data.get("desc")
query_data.programmer = serializer_obj.validated_data.get("programmer")
query_data.tester = serializer_obj.validated_data.get("tester")
query_data.publish_app = serializer_obj.validated_data.get("publish_app")
# 保存更新的数据
query_data.save()
# 序列化输出,展示数据
serializer_obj1 = ProjectSerializer(instance=pro)
return JsonResponse(serializer_obj1.data, json_dumps_params={"ensure_ascii": False})
# 删除数据
def delete(self, request, pk):
ret = {
"msg": "删除成功!"
}
ret_error = {
"msg": "传参异常",
"code": 404
}
try:
# 根据id查出对应数据
query_data = ProjectsModel.objects.get(pk=pk)
# 删除指定数据
query_data.delete()
# 一般删除数据的输出为None
except Exception:
return JsonResponse(ret_error, json_dumps_params={"ensure_ascii": False}, status=200)
return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=200)
class ProjectsViews(View):
# 查询全部数据
def get(self, request):
pro_data = ProjectsModel.objects.all()
serializer_obj=ProjectSerializer(instance=pro_data,many=True)
return JsonResponse(serializer_obj.data, safe=False, json_dumps_params={"ensure_ascii": False}, status=200)
# 创建数据
def post(self, request):
ret = {
"msg": "传参异常",
"code": 404
}
try:
json_str = request.body.decode('utf-8')
data_dict = json.loads(json_str)
# 如果入参不是json格式数据,抛出异常
except json.JSONDecodeError:
return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404)
# 反序列化输入
serializer_obj = ProjectSerializer(data=data_dict)
if not serializer_obj.is_valid(raise_exception=True):
ret.update(serializer_obj.errors)
return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404)
create_data = ProjectsModel.objects.create(**serializer_obj.validated_data)
#序列化输出
serializer_obj1=ProjectSerializer(instance=create_data)
return JsonResponse(serializer_obj1.data, json_dumps_params={"ensure_ascii": False}, status=200)
序列化输出:
- 将模型类对象传递给instance,会返回一个序列化器类对象
- 可以使用序列化器对象的data属性,获取序列化之后的数据(字典或者嵌套字典的列表)
- 如果传递的是查询集对象,那么需要添加many=True
反序列化输入:
- 将字典类型或者(嵌套字典的列表)传递给data参数,会返回一个序列化器类对象
- 必须先调用序列化器类对象.is_valid()方法,才会开始校验参数,检验成功会返回True,否则返回False
- 可以使用序列化器类对象.errors属性,获取报错信息(字典类型)
- 可以使用序列化器类对象.validated_data属性,获取校验通过之后的数据
- is_valid()方法,可以设置raise_exception=True,那么校验不通过,会抛出异常