序化器Serializer
Serializer序列化器两个功能:
1、序列化数据,将ORM获取的数据库QuerySet或数据对象【序列化成】Json格式
2、请求数据格式校验(底层调用Django的Form和ModelForm)
序列化数据
Serializer类序列化
models.py
from django.db import models class Role(models.Model): title = models.CharField(verbose_name="标题", max_length=32) order = models.IntegerField(verbose_name="顺序")
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models class UserInfoSerializer(serializers.Serializer): id = serializers.IntegerField() title = serializers.CharField() order = serializers.IntegerField() class UserView(APIView): def get(self, request): # 1、数据库获取多条数据 obj.title obj.order obj.count # queryset = models.Role.objects.all() [obj,obj,obj] # ser = UserInfoSerializer(instance=queryset, many=True) # 2、序列化器转换JSON格式:int/str/list/dict/ datetime/decimal 序列化器 # 数控获取单条数据 queryset = models.Role.objects.all().first() ser = UserInfoSerializer(instance=queryset) print(ser.data) return Response({"code": 0, "data": ser.data}) # 3、返回给用户
ModelSerializer类序列化
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models class UserModelSerializer1(serializers.ModelSerializer): class Meta: model = models.Role #fields = "__all__" #fields = ["id","title","order"] exclude = ["id"] class UserView(APIView): def get(self, request): # 1、数据库获取多条数据 # queryset = models.Role.objects.all() # ser = UserModelSerializer1(instance=queryset, many=True) # 2、数控获取单条数据 queryset = models.Role.objects.all().first() ser = UserModelSerializer1(instance=queryset) print(ser.data) return Response({"code": 0, "data": ser.data})
很显然,如果要对数据表中的字段进行序列化,使用ModelSerializer是要比Serializer更简洁一些的。
字段和参数
在ModelSerializer和Serializer中都可以自定义字段/方法,并传入一些相关参数。
models.py
from django.db import models # Create your models here. class Role(models.Model): """角色表""" title = models.CharField(verbose_name="名称", max_length=32) class Department(models.Model): """部门表""" title = models.CharField(verbose_name="名称", max_length=32) class UserInfo(models.Model): """用户表""" level_choices = ((1, "普通会员"), (2, "VIP"), (3, "SVIP"),) level = models.IntegerField(verbose_name="级别", choices=level_choices, default=1) username = models.CharField(verbose_name="用户名", max_length=32) password = models.CharField(verbose_name="密码", max_length=64) age = models.IntegerField(verbose_name="年龄", default=0) email = models.CharField(verbose_name="邮箱", max_length=64) token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True) # 外键 depart = models.ForeignKey(verbose_name="部门", to="Department", on_delete=models.CASCADE) # 多对多 roles = models.ManyToManyField(verbose_name="角色", to="Role") ctime = models.DateTimeField(verbose_name="创建时间",blank=True,null=True)
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models class UserModelSerializer2(serializers.ModelSerializer): level = serializers.CharField(source="get_level_display") #自定义字段 序列化choices类型 ctime = serializers.DateTimeField(format("%Y-%m-%d %X")) # 序列化datetime类型 title = serializers.CharField(source="depart.title") # 序列化外键字段 first_name = serializers.CharField(source="username") # 自定义字段 user_combination_info = serializers.SerializerMethodField() # 自定义方法 roles = serializers.SerializerMethodField() # 自定义方法对关联表数据进行序列化 class Meta: model = models.UserInfo fields = ["username", "first_name", "age", "level", "email", "ctime", "title", "user_combination_info", "roles"] def get_user_combination_info(self, obj): user_info = dict() user_info["username"] = obj.username user_info["age"] = obj.age user_info["email"] = obj.email print(user_info) return user_info def get_roles(self, obj): li_data = [] for i in obj.roles.all(): li_data.append(i.title) return li_data class UserView(APIView): def get(self, request): # 1、数据库获取多条数据 queryset = models.UserInfo.objects.all() ser = UserModelSerializer(instance=queryset, many=True) print(ser.data) return Response({"code": 0, "data": ser.data})
序列化类嵌套
主要是ORM类中对应ForeignKey和ManyToManyField的字段进行序列化
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models # 嵌套序列化类处理foreignkey和m2m class DepartSerializer(serializers.ModelSerializer): "外键" class Meta: model = models.Department fields = "__all__" class RoleSerializer(serializers.ModelSerializer): """多对多""" class Meta: model = models.Role fields = "__all__" class UserModelSerializer1(serializers.ModelSerializer): """嵌套处理一对多,多对多关系""" depart = DepartSerializer() # 一对多 roles = RoleSerializer(many=True) # 多对多 class Meta: model = models.UserInfo fields = ["username", "age", "depart", "roles"] class UserView(APIView): def get(self, request): # models.UserInfo.objects.update(ctime=datetime.datetime.now()) # 1、数据库获取多条数据 queryset = models.UserInfo.objects.all() ser = UserModelSerializer1(instance=queryset, many=True) print(ser.data) return Response({"code": 0, "data": ser.data})
序列化类继承
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models # 继承 class MySerializer(serializers.Serializer): more = serializers.SerializerMethodField() def get_more(self,obj): return "123" class UserModelSerializer2(serializers.ModelSerializer,MySerializer): # 继承序列化类 level = serializers.CharField(source="get_level_display") # choices类型 ctime = serializers.DateTimeField(format("%Y-%m-%d %X")) # datetime类型 title = serializers.CharField(source="depart.title") # 外键 first_name = serializers.CharField(source="username") # 自定义字段 user_combination_info = serializers.SerializerMethodField() # 自定义方法 roles = serializers.SerializerMethodField() # 自定义方法处理m2m class Meta: model = models.UserInfo fields = ["username", "first_name", "age", "level", "email", "ctime", "title", "user_combination_info", "roles","more"] def get_user_combination_info(self, obj): user_info = dict() user_info["username"] = obj.username user_info["age"] = obj.age user_info["email"] = obj.email print(user_info) return user_info def get_roles(self, obj): li_data = [] for i in obj.roles.all(): li_data.append(i.title) return li_data class UserView(APIView): def get(self, request): # models.UserInfo.objects.update(ctime=datetime.datetime.now()) # 1、数据库获取多条数据 queryset = models.UserInfo.objects.all() ser = UserModelSerializer2(instance=queryset, many=True) print(ser.data) return Response({"code": 0, "data": ser.data})
数据校验
请求发送过来的数据是多种结构,使用Serializer做多种结构判断;
内置校验:
CharField(required=True,max_length=20,min_length=6) IntegerField(required=False,max_value=100,min_value=11) ChoiceField(choices=[(1,"高级"),(2,"中级")] EmailFields()
正则校验:
CharField(label="邮箱2", validators=[RegexValidator(r"^\w+@\w+\.\w+$"), ])
钩子校验:
def validate_email3(self, value): """钩子函数,用于验证某个字段""" if re.match(r"^\w+@\w+\.\w+$", value): return value raise exceptions.ValidationError("邮箱格式错误")
示例1:基于Serializer数据校验
views.py
import re from django.core.validators import EmailValidator from django.core.validators import RegexValidator from rest_framework import exceptions from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models """ 用户提交数据校验 """ class UserSerializer(serializers.Serializer): username = serializers.CharField(label="姓名", min_length=6, max_length=32) age = serializers.IntegerField(label="年龄", min_value=8, max_value=200) level = serializers.ChoiceField(label="级别", choices=models.UserInfo.level_choices) email = serializers.CharField(label="邮箱") email1 = serializers.EmailField(label="邮箱1") email2 = serializers.CharField(label="邮箱2", validators=[RegexValidator(r"^\w+@\w+\.\w+$"), ]) email3 = serializers.CharField(label="邮箱3") def validate_email3(self, value): """钩子函数,用于验证某个字段""" if re.match(r"^\w+@\w+\.\w+$", value): return value raise exceptions.ValidationError("邮箱格式错误") # 基于Serializer class UserView(APIView): """用户管理""" def post(self, request): """添加用户""" ser = UserSerializer(data=request.data) if not ser.is_valid(): # 校验不通过 return Response({"code": 1006, "data": ser.errors}) # 校验通过 print(ser.validated_data) # 保存到数据库 return Response({"code": 0, "data": "创建成功"})
执行结果:
示例2:基于ModelSerializer校验
models.py
from django.db import models # Create your models here. class Role(models.Model): """角色表""" title = models.CharField(verbose_name="名称", max_length=32) class Department(models.Model): """部门表""" title = models.CharField(verbose_name="名称", max_length=32) class UserInfo(models.Model): """用户表""" level_choices = ((1, "普通会员"), (2, "VIP"), (3, "SVIP"),) level = models.IntegerField(verbose_name="级别", choices=level_choices, default=1) username = models.CharField(verbose_name="用户名", max_length=32) password = models.CharField(verbose_name="密码", max_length=64) age = models.IntegerField(verbose_name="年龄", default=0) email = models.CharField(verbose_name="邮箱", max_length=64) token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True) # 外键 depart = models.ForeignKey(verbose_name="部门", to="Department", on_delete=models.CASCADE) # 多对多 roles = models.ManyToManyField(verbose_name="角色", to="Role")
views.py
from django.core.validators import EmailValidator from django.core.validators import RegexValidator from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from apps.app03 import models class UserModelSerializer(serializers.ModelSerializer): email2 = serializers.CharField(label="邮箱2",validators=[RegexValidator(r"^\w+@\w+\.\w+$"),]) email3 = serializers.EmailField(label="邮箱3") class Meta: model = models.UserInfo fields = ["username","age","email","email2","email3"] extra_kwargs = { "username":{"min_length":6,"max_length":32}, } class UserView(APIView): def post(self, request): # 1、数据校验 ser = UserModelSerializer(data=request.data) if not ser.is_valid(): return Response({"code": 1006, "data": ser.errors}) ser.validated_data.pop("email2") # 多的字段踢出 ser.validated_data.pop("email3") ser.save(level=1, password="123456", depart_id=1) # 没有提交的字段,通过关键字参数形式添加 return Response({"code": 0, "data": "创建成功"})
save()方法会返回新生成数据对象。
执行结果:
示例3:基于ModelSerializer(FK+M2M)
views.py
# 基于ModelSerializer(FK+M2M) class UserModelSerializer(serializers.ModelSerializer): email2 = serializers.CharField(label="邮箱2", validators=[RegexValidator(r"^\w+@\w+\.\w+$"), ]) email3 = serializers.CharField(label="邮箱3") class Meta: model = models.UserInfo # depart 外键FK ,roles 多对多M2M fields = ["username", "age", "email", "depart", "roles", "email2", "email3"] extra_kwargs = { "username": {"min_length": 6, "max_length": 32}, } def validate_email3(self, value): """钩子函数,用于验证某个字段""" if re.match(r"^\w+@\w+\.\w+$", value): return value raise exceptions.ValidationError("邮箱格式错误") class UserView(APIView): def post(self, request): # 1、提交数据进行校验 ser = UserModelSerializer(data=request.data) if not ser.is_valid(): return Response({"code": 1006, "data": ser.errors}) ser.save() return Response({"code": 0, "data": "创建成功"})
执行结果: