序列化的目的是从数据库获取的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、ModelSerializer
和Serializer
自定义字段和参数
在ModelSerializer
和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
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类中对应ForeignKey
和 ManyToManyField
的字段进行序列化。
- 基于
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)