drf源码_序列化器

序列化的目的是从数据库获取的QuerySet或者数据对象,转化为 字典类型(JSON格式)
因为json.dumps 只能转换常见的字典、列表、等类型,不能转换从数据库直接查询出来的
对象 或者queryset列表 所以需要序列化

1、Serializer

from django.db import models
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import models

创建表
class Role(models.Model):
    title = models.CharField(verbose_name="标题", max_length=32)
    order = models.IntegerField(verbose_name="顺序")

 
创建序列化类
class InfoSerializer(serializers.Serializer):
    # 这些字段名称和类型需要跟对应被序列化的数据库的名称一致且对应的Field类型要一致
    id = serializers.IntegerField()
    title = serializers.CharField()
    order = serializers.IntegerField()


 序列化过程
class InfoView(APIView):
    def get(self, request):
        
        # 1.数据库获取多条数据,对Queryset序列化,要many改为True
        #[obj1,obj2,obj3,...]
        # queryset = models.Role.objects.all()
        # ser = InfoSerializer(instance=queryset, many=True)

        # 2.数据库获取单条数据
        instance = models.Role.objects.all().first()
        ser = InfoSerializer(instance=instance, many=False)
        
        
        print(type(ser.data), ser.data)  
        return Response(ser.data)

2、ModelSerializer

from django.db import models
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import models

角色表
class Role(models.Model):
    title = models.CharField(verbose_name="标题", max_length=32)
    order = models.IntegerField(verbose_name="顺序")
    
序列化类 ModelSerializer不用对应的写每个字段,model = models.Role
可以锁定表,ModelSerializer 会逐步检查表中的每个字端,然后生成对应的
serializer字段对象,serializer中的Field 跟 Models 中的Field类型
是对应的
class InfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Role
        序列化所有字段
        # fields = "__all__"
        只序列化某些字段
        # fields = ['id', 'title', 'order']
        #排处某个字段
        exclude = ["id"]


class InfoView(APIView):
    def get(self, request):
        # 1.数据库获取多条数据
        # queryset = models.Role.objects.all()
        # ser = InfoSerializer(instance=queryset, many=True)

        # 2.数据库获取单条数据
        instance = models.Role.objects.all().first()
        ser = InfoSerializer(instance=instance, many=False)

        print(type(ser.data), ser.data)
        return Response(ser.data)

很显然,如果要对数据表中的字段进行序列化,使用ModelModelSerializer是要比Serializer更简洁一些的。

3、ModelSerializerSerializer 自定义字段和参数

ModelSerializerSerializer中都可以自定义字段,并传入一些相关参数。

from django.db import models
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import models

lass Role(models.Model):
    title = models.CharField(verbose_name="标题", max_length=32)
    order = models.IntegerField(verbose_name="顺序")


class UserInfo(models.Model):
    name = models.CharField(verbose_name="姓名", max_length=32)
    gender = models.SmallIntegerField(verbose_name="性别", choices=((1, "男"), (2, "女")))
    role = models.ForeignKey(verbose_name="角色", to="Role", on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)

class InfoSerializer(serializers.ModelSerializer):
    # 自定义字段,可以通过从数据库查询对象中取值的  
    # 如 obj.xx 都可以 写在souce的后面
    # 比如 obj.get_gendery_display 可以获取choices中的中文值,同样可以写入到source后面,自定义字段名称可以随便取,如果跟数据库原有字段同名那就是重写了
    # obj.role  代表取role一行的对象,obj.role_id 代表取对应的id
    # 所以可以obj.role.title 跨表取title值,对应的souce是 role.title
    gender_text = serializers.CharField(source="get_gender_display")
    role = serializers.CharField(source="role.title")
    # 应该是直接找到数据库对应的DateTimeField 然后修改格式
    ctime = serializers.DateTimeField(format="%Y-%m-%d")
    # 找到name字段
    other_name = serializers.CharField(source="name")
    # 触发 get_mine 函数,get_mine函数返回什么,mine就返回什么
    mine = serializers.SerializerMethodField()

    class Meta:
        model = models.UserInfo
        fields = ['id', 'name', 'gender_text', "role", 'ctime', "other_name", "mine"]

    自定义的函数,obj代表每次序列化时传进的当前的对象
    def get_mine(self, obj):
        return "x-x-{}".format(obj.name)


class InfoView(APIView):
    def get(self, request):
        queryset = models.UserInfo.objects.all()
        ser = InfoSerializer(instance=queryset, many=True)
        print(type(ser.data), ser.data)
        return Response(ser.data)

4、序列化类嵌套

主要是ORM类中对应ForeignKeyManyToManyField的字段进行序列化。

  • 基于SerializerMethodField自定义方法对关联表数据进行序列化
  • 基于嵌套的序列化类实现
from django.db import models

定义Role表
class Role(models.Model):
    title = models.CharField(verbose_name="标题", max_length=32)
    order = models.IntegerField(verbose_name="顺序")

定义Tag表
class Tag(models.Model):
    caption = models.CharField(verbose_name="名称", max_length=32)

定义UserInfo表
class UserInfo(models.Model):
    name = models.CharField(verbose_name="姓名", max_length=32)
    gender = models.SmallIntegerField(verbose_name="性别", choices=((1, "男"), (2, "女")))
    role = models.ForeignKey(verbose_name="角色", to="Role", on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)
	
    # 除了下面的嵌套,也可以在定义中取多对多对应的字段
    #一个当前的 obj.tags.all() 获取当前的obj所有的tags对象,一个obj有可能获取多个tags对象
    # 所有要加个all
    tags = models.ManyToManyField(verbose_name="标签", to="Tag")

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import models

# 对Role表建立序列化器,被嵌套的表序列化器也同样支持自定义字段
# 增加字段,删除字段 和自定义get_xxx方法
class RoleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Role
        # fields = "__all__"
        fields = ["id", 'title']

# 对Tag表建立序列化器
class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Tag
        fields = "__all__"


class InfoSerializer(serializers.ModelSerializer):
    # 嵌套role表序列化器
    role = RoleSerializer()
    # 嵌套tags表序列化器,Tag是多对多 many参数改为True(后面需要细究)
    # 因为当前的obj会对应多个tags对象,所以这个地方many改为True
    # 当然后面还需要细究
    tags = TagSerializer(many=True)

    class Meta:
        model = models.UserInfo
        fields = ['id', 'name', "role", "tags"]


class InfoView(APIView):
    def get(self, request):
        queryset = models.UserInfo.objects.all()
        ser = InfoSerializer(instance=queryset, many=True)
        print(type(ser.data), ser.data)
        return Response(ser.data)

5、序列化继承

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import models


class MySerializer(serializers.Serializer):
    more = serializers.SerializerMethodField()

    def get_more(self, obj):
        return "123"


# InfoSerializer 继承 MySerializer 序列化器,more字段也可以使用
class InfoSerializer(serializers.ModelSerializer, MySerializer):
    class Meta:
        model = models.UserInfo
        fields = ["id", "name", 'more']


class InfoView(APIView):
    def get(self, request):
        instance = models.UserInfo.objects.all().first()
        ser = InfoSerializer(instance=instance, many=False)

        print(type(ser.data), ser.data)
        return Response(ser.data)
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值