九、Drf序列化器

九、序列化器

9.1序列化

从数据库取QuerySet或数据对象转换成JSON

9.1.1序列化器的简易使用
python 复制代码
#新建一张部门表
class Depart(models.Model):
    title=models.CharField(verbose_name='部门',max_length=32)
    order=models.IntegerField(verbose_name='顺序')
    count=models.IntegerField(verbose_name='人数')
python 复制代码
#新建路由
urlpatterns = [  
    path('api/<str:version>/depart/',views.DepartView.as_view(),name='depart'),
    

]
python 复制代码
#创建一个序列化器
from rest_framework import serializers
class DepartSerializers(serializers.Serializer):
    #部门系列化器,字段需要和数据库中的字段相对应
    title=serializers.CharField()
    order=serializers.IntegerField()
    count=serializers.IntegerField()
python 复制代码
#创建视图类
class DepartView(APIView):
    #无需认证
    authentication_classes = []
    #部门视图类
    def get(self,request,*args,**kwargs):
        #1、获取数据库中的数据
        depart_obj=models.Depart.objects.all().first()
        #2、序列化器转换成JSON
        ser_obj=DepartSerializers(instance=depart_obj)
        #打印ser_obj.data类型
        print('ser_obj.data.type:',type(ser_obj.data))

        #3、返回给用户
        context={
            'status':True,
            'data':ser_obj.data
        }
        return Response(context)

使用postman发送get请求进行测试

打印输出ser_obj.data的类型,是一个字典

python 复制代码
ser_obj.data.type: <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
9.1.2序列化QuerySet列表(多个数据对象)
python 复制代码
#视图类
class DepartView(APIView):
    #无需认证
    authentication_classes = []
    #部门视图类
    def get(self,request,*args,**kwargs):
        #1、获取数据库中的数据
        #获取表中的所有记录(多个数据对象,是一个QuerySet列表)
        depart_objs=models.Depart.objects.all()
        #2、序列化器转换成JSON,many代表允许多个数据对象
        ser_obj=DepartSerializers(instance=depart_objs,many=True)
        print('ser_obj.data.type:',type(ser_obj.data))

        #3、返回给用户
        context={
            'status':True,
            'data':ser_obj.data
        }
        return Response(context)

使用postman发送GET请求进行测试

打印输出ser_obj.data的类型,是一个列表

python 复制代码
ser_obj.data.type: <class 'rest_framework.utils.serializer_helpers.ReturnList'>
9.1.3ModelSerializer
python 复制代码
#创建序列化器
from rest_framework import serializers
class DepartSerializers(serializers.ModelSerializer):
    #部门系列化器
    class Meta:
        model = models.Depart
        #获取数据库中的所有字段
        fields = "__all__"
        #指定字段
        # fields = ['title','order','count']
        #排除字段
        # exclude=['count']

这个效果同9.2.2中的效果

9.1.4特殊字段的处理
python 复制代码
#表结构
class Depart(models.Model):
	#部门表
    title=models.CharField(verbose_name='部门',max_length=32)
    order=models.IntegerField(verbose_name='顺序')
    count=models.IntegerField(verbose_name='人数')

class userInfo(models.Model):
	#员工信息表
    name=models.CharField(verbose_name='姓名',max_length=32)
    GENDER_CHOICES=(
        (1,'男'),
        (2,'女')
    )
    #choices字段
    gender = models.SmallIntegerField(verbose_name='性别', choices=GENDER_CHOICES)
    #ForeignKey字段
    depart=models.ForeignKey(verbose_name='部门',to=Depart,on_delete=models.CASCADE)
    #DateTime字段
    ctime=models.DateTimeField(verbose_name='创建时间',auto_now=True)
python 复制代码
#创建路由
urlpatterns = [   
    path('api/<str:version>/depart/',views.DepartView.as_view(),name='depart'),
    path('api/<str:version>/userinfo/',views.userInfoView.as_view(),name='userinfo'),  

]
python 复制代码
#序列化器类
class UserInfoSerializers(serializers.ModelSerializer):
    #部门系列化器
    #新增一个choices字段,并获取choices中的文本
    gender_text=serializers.CharField(source='get_gender_display')
    #新增一个ForeignKey字段,并获取关联表中的文本
    depart_text=serializers.CharField(source='depart.title')
    #修改ctime类,并进行格式化
    ctime=serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    #新增一个数据库中不存在的字段
    xxx=serializers.SerializerMethodField()
    class Meta:
        model = models.userInfo
        fields = ['name','gender','gender_text','depart','depart_text','ctime','xxx']
    def get_xxx(self,obj):
        #这个函数返回什么,xxx这个字段就等于什么。
        #obj代表当前数据对象,obj.name就是当前数据对象中的name字段值
        return 'I am {}'.format(obj.name)
python 复制代码
#视图类
class userInfoView(APIView):
    # 用户视图类
    # 无需认证
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        # 1、获取数据库中的数据
        # 多条数据
        userInfo_objs = models.userInfo.objects.all()
        # 2、序列化器转换成JSON,many代表允许多个数据对象
        ser_obj = UserInfoSerializers(instance=userInfo_objs, many=True)
        print('ser_obj.data.type:', type(ser_obj.data))

        # 3、返回给用户
        context = {
            'status': True,
            'data': ser_obj.data
        }
        return Response(context)

使用postman发送GET请求进行测试

9.1.5通过序列化器的嵌套来处理m2m字段
python 复制代码
#表结构:
class Auther(models.Model):
	#著作表
    name=models.CharField(verbose_name='作者',max_length=32)

class Book(models.Model):
	#图书表
    title=models.CharField(verbose_name='书名',max_length=128)
    #auther为MToM类型,并关联到Auther
    #一个著作可以有多本书
    auther=models.ManyToManyField(verbose_name='作者',to=Auther,related_name='books')
python 复制代码
#创建url
urlpatterns = [
    path('api/<str:version>/auther/',views.AutherView.as_view(),name='auther'),
    p

]
python 复制代码
#图书序列化器
class BookSerializers(serializers.ModelSerializer):
    #书系列化器
    class Meta:
        model = models.Book
        fields = '__all__'
python 复制代码
#著作序列化器
class AutherSerializers(serializers.ModelSerializer):
    #著者系列化器
    #books字段通过上面创建的图书序列化器来进行序列化
    books=BookSerializers(many=True)
    class Meta:
        model = models.Auther
        fields = ['name','books']
python 复制代码
#视图类
class AutherView(APIView):
    # 用户视图类
    # 无需认证
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        # 1、获取数据库中的数据
        # 多条数据
        auther_objs = models.Auther.objects.all()
        # 2、序列化器转换成JSON,many代表允许多个数据对象
        ser_obj = AutherSerializers(instance=auther_objs, many=True)
        # print('ser_obj.data.type:', type(ser_obj.data))

        # 3、返回给用户
        context = {
            'status': True,
            'data': ser_obj.data
        }
        return Response(context)

通过postman发送请求进行测试

9.1.6序列化器的继承
python 复制代码
class BaseSerializers(serializers.Serializer):
    #基础序列化器
    #这里定义了一个xxx字段,数据来源是数据对象中的name属性
    xxx=serializers.CharField(source='name')
class BookSerializers(serializers.ModelSerializer):
    #书系列化器
    class Meta:
        model = models.Book
        fields = '__all__'

class AutherSerializers(serializers.ModelSerializer,BaseSerializers):
    #这个序列化器继承了BaseSerializers,所以也可以使用BaseSerializers中的xxx字段
    #著者系列化器
    books=BookSerializers(many=True)
    class Meta:
        model = models.Auther
        fields = ['name','books','xxx']

9.2使用序列化器校验数据

9.2.1基本校验
python 复制代码
#创建url
urlpatterns = [   
    path('login/', views.LoginView.as_view()),   

]
python 复制代码
#创建序列化器
class LoginSerializers(serializers.Serializer):
    #required=True代表不允许为空,默认值就是True
    name=serializers.CharField(required=True)
    password=serializers.CharField(required=True)
python 复制代码
#视图类
class LoginView(MyAPIView):
    #用户登入,不需要认证
    authentication_classes = []
    def post(self,request):
        #序列化用户传递过来的数据
        ser_obj=LoginSerializers(data=request.data)
        if ser_obj.is_valid():
            #如果数据有效,则将有效的数据返回给用户
            return Response(ser_obj.validated_data)
        #如果数据无效,则返回错误信息
        return Response(ser_obj.errors)

使用postman进行测试


9.2.2内置检验和正则表示式检验
python 复制代码
#创建序列化器
from rest_framework import serializers
from django.core.validators import RegexValidator
class LoginSerializers(serializers.Serializer):
    name=serializers.CharField(required=True)
    #password字段最大长度为32,最小长度为8
    password=serializers.CharField(required=True,max_length=32,min_length=8)
    #order字段最大值为100,最小值为10
    order=serializers.IntegerField(required=False,max_value=100,min_value=10)
    #gender只允许为1或2
    gender=serializers.ChoiceField(choices=((1,'男'),(2,'女')))
    #EmailField必须输入Email格式的数据
    email=serializers.EmailField(required=True)
    #手机号字段使用正则表达式检验,必须满足正则表达式的规则才能通过校验
    mobilePhone=serializers.CharField(validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$','手机号格式错误')])

使用postman进行测试

9.2.3钩子校验
python 复制代码
#序列化器
from rest_framework import serializers
from rest_framework import exceptions
class LoginSerializers(serializers.Serializer):
    name=serializers.CharField(required=True)
    password=serializers.CharField(required=True,max_length=32,min_length=6)

    def validate_name(self,value):
        #对某个字段进行钩子检验
        user_obj=models.User.objects.filter(name=value).first()
        if not user_obj:
            #如果用户名不存在,则抛出错误信息
            raise exceptions.ValidationError("用户名不存在")
        return value
    def validate(self, attrs):
        #全局中钩子检验
        name=attrs.get('name')
        password=attrs.get('password')
        user_obj=models.User.objects.filter(name=name,password=password).first()
        if not user_obj:
            #如果密码错误不存在,则抛出错误信息
            raise exceptions.ValidationError('密码错误')
        return attrs
9.2.4ModelSerializer进行数据校验
python 复制代码
#创建Model序列化器(用于数据校验)
class RegisterModelSerializers(serializers.ModelSerializer):
    confirm_password=serializers.CharField(required=True)
    class Meta:
        model=models.User
        fields=['name','password','confirm_password','depart']
        extra_kwargs={
            #为各个字段添加参数
            'name': {'max_length':32,'min_length':2},
            'password': {'validators':[RegexValidator(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$')]},
        }

    def validate_confirm_password(self, value):
        #确认密码钩子校验
        password=self.initial_data.get('password',None)
        if password != value:
            raise exceptions.ValidationError('两次输入密码不一致')
        return value
python 复制代码
#创建Model序列化器(用于序列化返回给用户的数据)
class UserSerializers(serializers.ModelSerializer):
    #role是chioces字段,这里可以获取它的文本内容
    role=serializers.CharField(source='get_role_display')
    #depart是ForeignKey字段,这里可以获取它的文本内容
    depart=serializers.CharField(source='depart.title')
    class Meta:
        model=models.User
        fields=["name","role","depart"]
python 复制代码
#视图类
class RegisterViews(APIView):
    # 用户登入,不需要认证
    authentication_classes = []
    def post(self,request):
        #通过序列化器校验用户传递过来的数据
        ser_obj=RegisterModelSerializers(data=request.data)
        #判断校验是否通过
        if ser_obj.is_valid():
			#如果校验通过,则删除数据库中不存在的字段,添加数据库中存在但用户未传递的字段
            ser_obj.validated_data.pop("confirm_password")
            instance=ser_obj.save(role=3)
            #通过序列化器序列化存入数据库中的数据,并返回给用户
            data = UserSerializers(instance=instance).data
            return Response(data)
        return Response(ser_obj.errors)

使用postman进行测试

9.2.5使用一个序列化器既做校验又做序列化
python 复制代码
#创建序列化器
class RegisterModelSerializers(serializers.ModelSerializer):
    #write_only=True代表只做校验,不做序列化
    confirm_password=serializers.CharField(required=True,write_only=True)
    #read_only=True代表只做序列化,不做校验
    role_text = serializers.CharField(source='get_role_display',read_only=True)
    depart_text=serializers.CharField(source='depart.title',read_only=True)
    class Meta:
        model=models.User
        fields=['name','password','confirm_password','role_text','depart','depart_text']
        extra_kwargs={
            #为各个字段添加参数
            'name': {'max_length':32,'min_length':2},
            #write_only=True代表只做校验,不做序列化
             'password': {"write_only":True,'validators':[RegexValidator(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$')]},
            #write_only=True代表只做校验,不做序列化
            'depart':{"write_only":True}
        }

    def validate_confirm_password(self, value):
        #确认密码钩子校验
        password=self.initial_data.get('password',None)
        if password != value:
            raise exceptions.ValidationError('两次输入密码不一致')
        return value
python 复制代码
#视图类
class RegisterViews(APIView):
    # 用户登入,不需要认证
    authentication_classes = []
    def post(self,request):
        ser_obj=RegisterModelSerializers(data=request.data)
        if ser_obj.is_valid():

            ser_obj.validated_data.pop("confirm_password")
            ser_obj.save(role=3)

            return Response(ser_obj.data)
        return Response(ser_obj.errors)

使用postman测试

相关推荐
PieroPc28 分钟前
Python 写的 智慧记 进销存 辅助 程序 导入导出 excel 可打印
开发语言·python·excel
云和数据.ChenGuang2 小时前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
梧桐树04294 小时前
python常用内建模块:collections
python
Dream_Snowar5 小时前
速通Python 第三节
开发语言·python
蓝天星空6 小时前
Python调用open ai接口
人工智能·python
jasmine s6 小时前
Pandas
开发语言·python
郭wes代码6 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
leaf_leaves_leaf6 小时前
win11用一条命令给anaconda环境安装GPU版本pytorch,并检查是否为GPU版本
人工智能·pytorch·python
夜雨飘零16 小时前
基于Pytorch实现的说话人日志(说话人分离)
人工智能·pytorch·python·声纹识别·说话人分离·说话人日志
404NooFound7 小时前
Python轻量级NoSQL数据库TinyDB
开发语言·python·nosql