django rest_framework 序列化器详解
2022年7月9日大约 4 分钟约 1064 字
模型数据序列化
创建一个序列化器
序列化器与django Form类的功能非常相似,Form类是用于前后端不分离项目的表单数据格式,而序列化器是用于前后端分离项目的JSON数据格式。
序列化器基类
编辑文件 users/serializers.py
from rest_framework import serializers
from .models import UserModel
class UserSerializer(serializers.Serializer):
"""用户模型的序列化/反序列化器"""
id = serializers.IntegerField(read_only=True)
username = serializers.CharField(max_length=150, help_text="用户名")
email = serializers.EmailField(allow_blank=True, required=False, help_text="邮箱")
first_name = serializers.CharField(max_length=150, allow_blank=True, required=False, help_text="名")
last_name = serializers.CharField(max_length=150, allow_blank=True, required=False, help_text="姓")
password = serializers.CharField(write_only=True, min_length=8, help_text="密码")
is_superuser = serializers.BooleanField(default=False, help_text="是否超级用户")
is_active = serializers.BooleanField(default=True, help_text="是否激活")
is_staff = serializers.BooleanField(default=False, help_text="是否员工")
date_joined = serializers.DateTimeField(read_only=True, help_text="注册时间")
last_login = serializers.DateTimeField(read_only=True, allow_null=True, help_text="最后登录时间")
# 自定义字段
name = serializers.CharField(max_length=50, allow_blank=True, required=False, help_text="名字")
birth_date = serializers.DateField(allow_null=True, required=False, help_text="生日")
gender = serializers.ChoiceField(choices=UserModel.GENDER_CHOICES, allow_blank=True, allow_null=True, required=False, help_text="性别")
avatar_img = serializers.ImageField(allow_null=True, required=False, help_text="头像路径")
address = serializers.CharField(max_length=100, allow_blank=True, required=False, help_text="地址")
mobile = serializers.CharField(max_length=11, allow_blank=True, allow_null=True, required=False, help_text="手机号")
# serializer是有直接保存到数据库的功能的,在这里写
# 根据提供的验证过后的数据,创建并返回一个新的'UserModel'模型实例
def create(self, validated_data):
"""创建用户"""
password = validated_data.pop('password', None)
user = UserModel(**validated_data)
if password:
user.set_password(password) # 使用Django的密码加密方法
user.save()
return user
# 根据提供的验证过后的数据,更新并返回一个已经存在的'UserModel'模型实例
def update(self, instance, validated_data):
"""更新用户"""
password = validated_data.pop('password', None)
# 更新所有字段
for attr, value in validated_data.items():
setattr(instance, attr, value)
# 如果提供了密码,则加密后设置
if password:
instance.set_password(password)
instance.save()
return instance
create()和update()方法是Serializer类必填方法,定义了在调用serializer.save()时如何创建和更新的模型实例。
模型序列化器类
编辑文件 persons/serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
from persons.models import PersonModel
class UserSerializer(serializers.ModelSerializer):
# person在用户模型中是反向关联关系,不会默认包含,需要手动添加显式字段
persons = serializers.PrimaryKeyRelatedField(many=True, queryset=PersonModel.objects.all())
class Meta:
model = User
fields = ('id', 'username', 'persons')
class PersonSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username') # 这里也可以使用CharField(read_only=True)
# owner = UserSerializer() # 替换默认字段,可以在json中显示外键的所有数据,而不是只显示id
class Meta:
model = PersonModel
fields = ('id', 'name', 'sex', 'age', 'mail', 'phone', 'owner')
# fields = "__all__" # 这里是映射模型的所有字段如果是外键会默认序列化成id编号,如果想要外键直接显示所有数据,需要手动写序列化器字段来覆盖默认自动生成的外键字段
提示
ModelSerializer类是直接继承Serializer类,并不神秘,额外仅仅做了:
- 一组自动确定的字段
- 默认简单的实现了create()和update()方法
超链接模型序列化器类
编辑文件 persons/serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
from persons.models import PersonModel
class PersonSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username') # 这里也可以使用CharField(read_only=True)
class Meta:
model = PersonModel
fields = ('id', 'name', 'sex', 'age', 'mail', 'phone', 'owner')
class UserSerializer(serializers.HyperlinkedModelSerializer):
# person在用户模型中是反向关联关系,不会默认包含,需要手动添加显式字段
persons = serializers.HyperlinkedRelatedField(many=True, view_name='person-detail', read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'persons', 'url')HyperlinkedModelSerializer与ModelSerializer区别:
- 默认情况下不包含id字段
- 它包含了一个url字段,HyperlinkedIdentityField
- 关联关系使用HyperlinkedRelatedField,而不是PrimaryKeyRelatedField
测试序列化器
python manage.py shell
from persons.models import PersonModel
from persons.serializers import PersonSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
# 描述序列化器实例的结构和字段(representation)
serializer = PersonSerializer()
print(repr(serializer))
# 创建一条模型数据
person1 = PersonModel(name='张三', sex=1)
person1.save()
# 将模型实例进行序列化
serializer1 = PersonSerializer(person1)
serializer1.data
json_bytes = JSONRenderer().render(serializer1.data)
# 将json字节码反序列化
from six import BytesIO
stream = BytesIO(json_bytes) # 将json字节码转成一个流(stream)
data1 = JSONParser().parse(stream) # 将流解析成python数据类型
serializer1 = PersonSerializer(data=data1) # 将数据转成序列化器
serializer1.is_valid() # 验证数据合法性
serializer1.validated_data # 查看已验证的数据
serializer1.save() # 保存到数据模型(数据库)
# 序列化查询集(querysets)
serializer2 = PersonSerializer(PersonModel.objects.all(), many=True)
serializer2.data