DRF-django_rest_framework序列化器的基本使用

63 阅读4分钟

序列化器的基本使用

为什么需要序列化器

在项目中经常需要对数据库惊醒查询并将结果转化成json格式返还给用户,而django的orm获取数据库可能时可能获取到多个对象-->[对象1,对象2...],l类型是QuerySet,不能直接使用json.dumps()转换成json格式

#数据类型
depart_object = models.Depart.objects.first()
print(type(depart_object))
#<class 'api.models.Depart'>

depart_object = models.Depart.objects.all()
print(type(depart_object))
#<class 'django.db.models.query.QuerySet'>

序列化器的基本使用

from rest_framework import serializers
class DepartSerializer(serializers.Serializer):
    title = serializers.CharField()
    count = serializers.IntegerField()
class DepartView(APIView):
    def get(self,request,*args,**kwargs):
        #1.获取数据库中的数据{'id':xxx,'tittle:'xxx'}
        depart_object = models.Depart.objects.all()
        #print(type(depart_object))
        #2.转换成json格式-->用json.dumps() 转换成json格式只支持 int/str/list/dict,   其他都不支持
        ser = DepartSerializer(instance=depart_object,many=True)
        print(ser.data)

        #3.返回给用户
        context = {'status':200,'data':ser.data}
        return Response(context)
    
#models
class Depart(models.Model):
    title = models.CharField(verbose_name='部门',max_length=20)
    order = models.IntegerField(verbose_name='顺序')
    count = models.IntegerField(verbose_name='人数')

当models中的定义的列比较多时,也可以继承ModelsSerializer更加简便的使用序列化器

class DepartSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Depart
        fields = "__all__"
        #指定返回的字段
        fields = ['title','order',]

如果数据库中存的时各种疑难杂症类型,如下,的也是可以系列化的

#mdoels
class UserInfo(models.Model):
    name = models.CharField(verbose_name='姓名',max_length=32)
    gender = models.SmallIntegerField(verbose_name='性别',choices=((1,'男'),(2,'女')))
    depart = models.ForeignKey(verbose_name='部门',to='Depart',on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name='时间',auto_now_add=True)
    
    

对于获取choice的数字对应的值可以使用类似django的modelform的写法的


class UserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source='get_gender_display')
    class Meta:
        model = models.UserInfo
        fields = "__all__"
'''        
{
    "status": 200,
    "data": [
        {
            "id": 1,
            "gender": "男",
            "name": "nim",
            "ctime": "2024-02-01T15:57:37.731296Z",
            "depart": 1
        },
        {
            "id": 2,
            "gender": "女",
            "name": "mm",
            "ctime": "2024-02-01T15:57:37.731296Z",
            "depart": 2
        }
    ]
}
'''
#即想要数字又想要文本?

class UserSerializer(serializers.ModelSerializer):
    gender_text = serializers.CharField(source='get_gender_display')
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['name','gender','gender_text',]
'''
        {
    "status": 200,
    "data": [
        {
            "name": "nim",
            "gender": 1,
            "gender_text": "男"
        },
        {
            "name": "mm",
            "gender": 2,
            "gender_text": "女"
        }
    ]
}
'''

外键想要显示具体的值:

class UserSerializer(serializers.ModelSerializer):
    depart = serializers.CharField(source='depart.title')
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['name','gender','gender_text','depart']
'''
{
    "status": 200,
    "data": [
        {
            "name": "nim",
            "gender": 1,
            "gender_text": "男",
            "depart": "技术部"
        },
        {
            "name": "mm",
            "gender": 2,
            "gender_text": "女",
            "depart": "运营部"
        }
    ]
}
'''

数据库的datetime类型,如果不想显示精确到年月日时分秒:

class UserSerializer(serializers.ModelSerializer):
    gender_text = serializers.CharField(source='get_gender_display')
    depart = serializers.CharField(source='depart.title')
    ctime = serializers.DateTimeField(format="%Y-%m-%d")
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['name','gender','gender_text','depart','ctime']
        
'''
{
    "status": 200,
    "data": [
        {
            "name": "nim",
            "gender": 1,
            "gender_text": "男",
            "depart": "技术部",
            "ctime": "2024-02-01"
        },
        {
            "name": "mm",
            "gender": 2,
            "gender_text": "女",
            "depart": "运营部",
            "ctime": "2024-02-01"
        }
    ]
}
'''

显示自定义字段

class UserSerializer(serializers.ModelSerializer):
    gender_text = serializers.CharField(source='get_gender_display')
    depart = serializers.CharField(source='depart.title')
    ctime = serializers.DateTimeField(format="%Y-%m-%d")
    
	#自定义
    MyDefine = serializers.SerializerMethodField()
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['name','gender','gender_text','depart','ctime','MyDefine']

    #自定义值
    def get_MyDefine(self,obj):
        #会执行get_   firlds里的字段名的方法获取对应的值
        return '123'
'''
        {
            "name": "nim",
            "gender": 1,
            "gender_text": "男",
            "depart": "技术部",
            "ctime": "2024-02-01",
            "MyDefine": "123"
        },
'''
	#自定义格式
    def get_MyDefine(self,obj):
        return '{}-{}-{}'.format(obj.name,obj.gender,obj.id)
    '''
            {
            "name": "nim",
            "gender": 1,
            "gender_text": "男",
            "depart": "技术部",
            "ctime": "2024-02-01",
            "MyDefine": "nim-1-1"
        }
    '''

标签

#models
class Tag(models.Model):
    caption = models.CharField(verbose_name='标签',max_length=32)


class UserInfo(models.Model):
    name = models.CharField(verbose_name='姓名',max_length=32)
    gender = models.SmallIntegerField(verbose_name='性别',choices=((1,'男'),(2,'女')))
    depart = models.ForeignKey(verbose_name='部门',to='Depart',on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name='时间',auto_now_add=True)

    tags = models.ManyToManyField(verbose_name='标签',to='Tag')
    
    

想获取到标签,只能使用自定义的方法:

class UserSerializer(serializers.ModelSerializer):
    gender_text = serializers.CharField(source='get_gender_display')
    depart = serializers.CharField(source='depart.title')
    ctime = serializers.DateTimeField(format="%Y-%m-%d")

    tag = serializers.SerializerMethodField()
    MyDefine = serializers.SerializerMethodField()
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['tag','name','gender','gender_text','depart','ctime','MyDefine']
    def get_tag(self,obj):
        # queryset = obj.tags
        #方式1 、使用列表推导式
        res = [{'id':tag.id,'caption':tag.caption}for tag in obj.tags.all() ]
        return res

针对foreign key 和many to many获取方法2:

嵌套

#用这个方法返回的可以从多个表里选择,可以返回任意的字段
class D1(serializers.ModelSerializer):
    class Meta:
        model = models.Depart
        fields = ['id','title']
class D2(serializers.ModelSerializer):
    class Meta:
        model = models.Tag
        fields = ['caption']
class UserSerializer(serializers.ModelSerializer):
    depart = D1()
    tags = D2(many=True)
    class Meta:
        model = models.UserInfo
        fields = ['tags','depart',还可以加上Userinof的字段]
        
#其他自定义的字段还可以在D1和D2里面定义

继承

#可以使用父类中的字段
class base(serializers.Serializer):
    xx = serializers.CharField(source='name')

class UserSerializer(serializers.ModelSerializer,base):
    depart = D1()
    tags = D2(many=True)
    class Meta:
        model = models.UserInfo
        fields = ['tags','depart','xx']

对比

class ser2(serializers.Serializer):
    #字段全部都需要自己写
    pass
class ser1(serializers.ModelSerializer):
	#可以使用class Meta: fields=[xx,xx,xxx]
    #不能继承serializers.ModelSerializer,能继承serializers.Serializer
    pass