欢迎来到赛兔子家园

序化器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": "创建成功"})

执行结果:

 

posted on 2024-03-26 17:14  赛兔子  阅读(0)  评论(0编辑  收藏  举报

导航