官方文档原文
ModelSerializer
类提供了一个快捷方式,可让你基于 Models
自动创建一个 Serializer
类,其中的字段与模型类字段对应。
ModelSerializer
类与常规 Serializer
类相同,不同之处在于:
它会根据模型自动生成一组字段。
它会自动为序列化类生成验证器,例如
unique_together
验证器。它包含
.create()
和.update()
的简单默认实现。
声明 ModelSerializer
如下所示:
from rest_framework import serializers
class AccountSerializer(serializers.ModelSerializer):
class Meta:
# 指定对哪个模型进行序列化
model = Account
# 指定包含哪些字段
fields = ('id', 'account_name', 'users', 'created')
默认情况下,该类中的所有模型类字段将被映射为相应的序列化类字段。
任何关系(如模型上的外键)都将映射到 PrimaryKeyRelatedField
。除非在序列化关系文档中指定,否则默认不包括反向关系。
检查 ModelSerializer
序列化类能够生成一个表示字符串,可以让你充分检查其字段的状态。在使用 ModelSerializer
进行工作时,这是特别有用的,你需要确定它为你自动创建了哪些字段和验证器。
为此,需要进入 Django shell,然后导入序列化类,实例化它并用 repr()
打印对象表示形式:
>>> from myapp.serializers import AccountSerializer
>>> serializer = AccountSerializer()
>>> print(repr(serializer))
AccountSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(allow_blank=True, max_length=100, required=False)
owner = PrimaryKeyRelatedField(queryset=User.objects.all())
这里会把自动生成的序列化器打印出来。
指定要包含的字段
如果你只希望在模型序列化程序中使用默认字段的子集,则可以使用 fields
或 exclude
选项来完成此操作,就像使用 ModelForm
一样。
强烈建议你显式使用 fields
属性序列化的所有字段。这将使你不太可能在模型更改时无意中暴露数据。
比如:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
你还可以将 fields
属性设置为特殊值 '__all__'
,以指示应该使用模型中的所有字段。
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = '__all__'
你可以将 exclude
属性设置为从序列化程序中排除的字段列表。
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
exclude = ('users',)
fields
和 exclude
属性中的名称通常映射到模型类的模型字段。
或者 fields
选项中的名称可以映射成属性或方法。而不会变成模型类中的参数。
从版本 3.3.0 开始,必须提供其中一个属性 fields
或 exclude
。
指定嵌套序列化
默认的 ModelSerializer
使用主键进行关联,但你也可以使用 depth
选项轻松生成嵌套表示(自关联)。
为了便于理解,这里我们用上一篇的 User 和 Profile 的关联模型来举例。
# serializers.py
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('city', 'owner')
depth = 1
现在设定了 depth = 1
,当我们在 shell 中执行下列操作时:
>>> u = Profile.objects.get(pk=1)
>>> serializer = ProfileSerializer(u)
>>> serializer.data
打印出来的 owner
将不仅仅是对应的 User
的主键,而是包括该 User 的所有字段:
ReturnDict([('city', 'shanghai'),
('owner',
OrderedDict([('id', 1),
('password','xxx'),
('last_login', '2018-05-03T15:08:04.022687Z'),
('is_superuser', True),
('username', 'diego'),
('first_name', ''),
('last_name', ''),
('email', ''),
('is_staff', True),
('is_active', True),
('date_joined', '2018-04-01T15:01:29.451391Z'),
('groups', []),
('user_permissions', [])]))])
默认情况下 depth = 0
,这时候序列化的关联对象将只包含该对象的主键:
ReturnDict([('city', 'shanghai'), ('owner', 1)])
显式指定字段
你可以将额外的字段添加到 ModelSerializer
,或者通过在类上声明字段来覆盖默认字段,就像你对 Serializer
类所做的那样。
class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
groups = serializers.PrimaryKeyRelatedField(many=True)
class Meta:
model = Account
额外的字段可以对应于模型上的任何属性或可调用的字段。
指定只读字段
你可能希望将多个字段指定为只读。不要显式给每个字段添加 read_only = True
属性,你可以使用快捷方式 Meta
选项 read_only_fields
。
该选项应该是字段名称的列表或元组,声明如下:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
read_only_fields = ('account_name',)
含有 editable = False
的模型字段,AutoField
字段默认设置为只读,并且不需要添加到 read_only_fields
选项。
注意: 有一种特殊情况,只读字段是模型级别的 unique_together
约束的一部分。在这种情况下,序列化类需要验证约束该字段,但也不能由用户编辑。
处理这个问题的正确方法是在序列化类中明确指定字段,同时提供 read_only = True 和 default = ...
关键字参数。
其中一个例子是与当前认证 User 的只读关系,它与另一个标识符是 unique_together
。在这种情况下,你会像这样声明用户字段:
user = serializers.PrimaryKeyRelatedField(
read_only=True,
default=serializers.CurrentUserDefault()
)
其他关键字参数
还有一个快捷方式允许你使用 extra_kwargs
选项在字段上指定任意附加关键字参数。与 read_only_fields
的情况一样,这意味着你不需要在序列化类中显式声明该字段。
该选项是一个字典,将字段名称映射到关键字参数字典。例如:
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'username', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user