开发项目是和 Django-ORM 相关的, 因此有应对 ORM 的 Serializers ModelSerializer。
序列化器不仅仅是对需要参数的声明,更是参数校验和标准化输出的策略,因此需要严格按照开发实际情况声明好字段约束。
关系字段用于表示模型关系的数据字段,它们可以应用到 ForeignKey、ManyToManyField 和 OneToOneField关系,以及对反向关系、自定义关系等。
Serializers fields 序列化字段
序列化字段类型和方法
序列化器中常用的字段类型,对于 DRF 框架中序列化器所有的字段类型,可以到 rest_framework.fields 模块中进行查看。序列化器类定义字段类型和 Django 框架中的字段类型一致,只需知道常用的字段类型即可,对于其他字段类型需要的时候再去查看。
根据 DRF 版本的不同,可能参数会有细微的调整。
BooleanField,布尔类型。
BooleanField()
NullBooleanField,可以接受 None 的布尔类型。
NullBooleanField()
CharField,文本字符串类型,可以检测验证字符串的长度是否符合 max_length 和 mix_length 等配置。
CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField,文本字符串类型,并验证文本是否符合邮件格式。
EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField,文本字符串类型,并验证字符串是否匹配强制参数 regex 所指定的正则表达式。
RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField,文本字符串类型,并验证字符串是否匹配正则表达式:[a-zA-Z0-9_-]
SlugField(maxlength=50, min_length=None, allow_blank=False)
URLField,文本字符串有效类型,并验证字符串是否符合 URL 规则。
URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField,UUID 字符串类型,表示类型 hex_verbose、hex、int、urn。
UUIDField(format='hex_verbose')
FilePathField,文本字符串类型,选择仅限于文件系统上某个目录中的文件名。
FilePathField(path, match=None, recursive=False, allow_files=True,allow_folders=False, required=None)
IPAddressField,文本字符串类型,输入为有效IPv4或IPv6字符串的字段。
IPAddressField(protocol='both', unpack_ipv4=False, **options)
IntegerField,整数数字类型。
IntegerField(max_value=None, min_value=None)
FloatField, 浮点数字类型。
FloatField(max_value=None, min_value=None)
DecimalField,小数点有效位类型。 [max_digits: 最多位数,decimal_palces: 小数点位置]。
DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
DateTimeField,日期和时间表示。
DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField,日期表示。
DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField,时间表示。
TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField,持续时间表示。
DurationField()
ChoiceField,可以接受一组有限选择中的值的字段,choices与Django的用法相同。
choices = ((1,"a"),(2,"b"))ChoiceField(choices)
MultipleChoiceField,可以接受一组空、一个、多个值的字段,choices与Django的用法相同。
choices = ((1,"a"),(2,"b"),(,"c"))MultipleChoiceField(choices)
FileField,文件表示,执行 Django 的 FileField 验证标准。
FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField,图像表示,验证上传的文件内容是否与已知图像格式匹配。
ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField,验证对象列表的字段类。
ListField(child=, min_length=None, max_length=None)
DictField,验证对象字典的字段类。
DictField(child=)
JSONField,验证数据结构是否包含有效的 JSON数据 。
JSONField()
ReadOnlyField,仅返回该字段的值而无需修改。
ReadOnlyField(Field)
HiddenField,不基于用户输入获取值,而是从默认值或可调用对象获取其值。
HiddenField(Field)
ModelField,可以绑定到任意模型字段的通用字段。
ModelField(Field)
SerializerMethodField,只读字段, 通过在附加的序列化器类上调用一个方法来获取值, 用于将任何类型的数据添加到对象的序列化。
SerializerMethodField(Field)
通用参数
任意字段类型都拥有的参数,根据开发的实际情况需要进行修改。
关键字参 | 数参数作用说明 |
read_only | 在更新或者创建资源的时候不应该包含的字段参数, 仅仅是只读数据的时候才需要反序列化,默认 False |
write_only | 在更新或创建资源的时候需要包含该字段参数, 而读取数据内容的时候将不会反序列化, 默认 False |
required | 如果反序列化过程中未提供字段,通常会引发错误,设置该字段是否为必填对象,默认 True |
default | 当提交对象中不包含该字段时, 使用自动填充的默认值,在局部更新的时候将不适用allow_null声明字段是否可以为空,默认 False |
source | 在对 ORM 字段重新声明新字段时,需要将新字段指明对应的 ORM 字段 |
validators | 验证器功能列表,应将其应用于传入字段输入,并且会引发 serializers.ValidationError 验证错误或返回验证数据 |
error_messages | 验证错误时需要返回的错误信息字典 |
label | 短文本字符串, 可用作 HTML 表单字段或其他描述性元素中的字段名称 |
help_text | 可用作在 HTML 表单字段或其他描述性元素中对该字段进行描述的文本字符串 |
initial | 该值应用于预先填充 HTML 表单字段的值 |
style | 键值对字典,可用于控制渲染器应如何渲染字段,HTML&Forms 文档 |
选项参数
特定字段类型才拥有的参数。
名称 | 作用 |
max_length | 最大长度 |
min_lenght | 最小长度 |
allow_blank | 是否允许为空 |
trim_whitespace | 是否截断空白字符 |
max_value | 最大值 |
min_value | 最小值 |
Model Serializer 模型序列化
ModelSerializer 是和常规 Serializer 类一样区别在于:
- 将根据模型自动为生成一组字段。
- 将自动为序列化器生成验证器, 例如 unique_together 验证器。
- 默认实现了简单的 .create() 和 .update() 方法。
默认情况下,该类上的所有模型字段都将映射到相应的序列化器字段。 模型上的任何关系都将映射到 PrimaryKeyRelatedField,默认情况下不包括反向关系,除非按照序列化器关系文档中的明确指定包含反向关系。
序列化基础实现方式
from django.db import modelsfrom rest_framework import serializersclass UserModel(models.Model): username = models.CharField(max_length=32, unique=True, null=False, blank=False) email = models.EmailField() ...class UserSerializer(serializers.ModelSerializer): class Meta: model = UserModel fields = ('id', 'username', 'email')
指定序列化字段
通过 fields 有选择的指定序列化的字段。
class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account fields = ['id', 'account_name', 'users', 'created']
通过 fields指定全部字段。
class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account fields = '__all__'
通过 exclude 进行排除某些字段。
class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account exclude = ['users']
嵌套序列化
如果模型中存在外键对象, 默认情况下使用外键 ID 包含外键对象,可以使用嵌套外键系列化对象进行输出,只需要提供 depth 参数,该 depth 选项应设置为整数值, 该值指示在嵌套对象需要表示的深度。
from rest_framework import serializersclass AccountSerializer(serializers.ModelSerializer): class Meta: model = Account fields = ['id', 'account_name', 'users', 'created'] depth = 1
自定义声明字段
类似 ORM 一样使用字段声明,只修改模型类字段的映射字段需要自己声明一个字段,使用 source 来指明该字段与模型中的哪个字段对应即可或者可以自定义其它字段,如果存在外键关联的情况则用 "__"来表示关系。
class AccountSerializer(serializers.ModelSerializer): data_type = serializers.CharField(source='category__itme', read_only=True) groups = serializers.PrimaryKeyRelatedField(many=True) class Meta: model = Account
设置只读字段
声明只读字段只需要将包含在 fields 中的字段添加到 read_only_fields 中,或者在自定义字段中加入 read_only=True 进行声明。
默认情况已设置 editable=False 的模型字段和 AutoField 字段将设置为只读,并且不需要将其添加到 read_only_fields 选项中。
class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account fields = ['id', 'account_name', 'users', 'created'] read_only_fields = ['account_name']
设置附加参数
允许使用 extra_kwargs 选项在指定字段上声明任意附加关键字参数和 read_only_fields 的情况一样不需要在序列化程序上显式声明该字段。
此选项是一个字典,将字段名称映射到关键字参数的字典,如果已在序列化程序类上显式声明了该字段,则该 extra_kwargs 选项将被忽略。
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
Hyperlinked 超链接序列化
HyperlinkedModelSerializer 类是类似于 ModelSerializer,不同之处在于使用的超链接来表示的关系,而不是主键类。
默认情况下序列化程序将包含一个 url 字段而不是主键字段,url 字段将使用 HyperlinkedIdentityField 序列化器字段表示,而模型上的任何关系都将使用 HyperlinkedRelatedField 序列化器字段表示。
class AccountSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Account fields = ['url', 'id', 'account_name', 'users', 'created']
实例化 HyperlinkedModelSerializer 必须在序列化器声明当前请求对象 request。
serializer = AccountSerializer(queryset, context={'request': request})
将链接变成绝对的携带主机地址。
http://api.example.com/accounts/1/
ListSerializer 列表序列化
如果自定义一个 ListSerializer 行为的序列化类,并具有以下功能
- 要提供列表的特定验证,检查一个元素与列表中的另一个元素没有冲突。
- 自定义多个对象的创建或更新行为,可以通过使用序列化 Meta 类上的 list_serializer_class 选项来修改在传递 many = True 时使用的类。
class CustomListSerializer(serializers.ListSerializer): ...class CustomSerializer(serializers.Serializer): ... class Meta: list_serializer_class = CustomListSerializer
实现创建多个对象。
class BookListSerializer(serializers.ListSerializer): def create(self, validated_data): books = [Book(**item) for item in validated_data] return Book.objects.bulk_create(books)class BookSerializer(serializers.Serializer): ... class Meta: list_serializer_class = BookListSerializer
在传递的多个实例对象的时候需要对应关系以及判断更新还是创建, 或者删除。
from rest_framework import serializersclass BookListSerializer(serializers.ListSerializer): def update(self, instance, validated_data): # 映射逻辑: # id -> instance # id -> data item book_mapping = {book.id: book for book in instance} data_mapping = {item['id']: item for item in validated_data} # 创建实例或更新实例 ret = [] for book_id, data in data_mapping.items(): book = book_mapping.get(book_id, None) if book is None: ret.append(self.child.create(data)) else: ret.append(self.child.update(book, data)) # 删除 for book_id, book in book_mapping.items(): if book_id not in data_mapping: book.delete() return ret
需要使用主键在列表中标识元素,使用可写字段而不要使用默认的只读字段。
class BookSerializer(serializers.Serializer): id = serializers.IntegerField() ... class Meta: list_serializer_class = BookListSerializer
动态自定义配置
需要动态的字段映射配置, 并不想定义多个类对象。
from rest_framework import serializersclass DynamicFieldsModelSerializer(serializers.ModelSerializer): """ fields参数,控制应显示字段。 """ def __init__(self, *args, **kwargs): # 不需要传参舍弃掉的fields fields = kwargs.pop('fields', None) # 额外注意 必须 # 正常实例化超类 super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) if fields is not None: # 删除所有在field参数中未指定的字段 allowed = set(fields) existing = set(self.fields) for field_name in existing - allowed: self.fields.pop(field_name)
Serializers Relations 序列化关系
model.py 模型定义
class Album(models.Model): album_name = models.CharField(max_length=100) artist = models.CharField(max_length=100)class Track(models.Model): album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE) order = models.IntegerField() title = models.CharField(max_length=100) duration = models.IntegerField() class Meta: unique_together = ['album', 'order'] ordering = ['order'] def __str__(self): return '%d: %s' % (self.order, self.title)
StringRelatedField
字段可以使得目标模型类的 __str__ 方法进行关系映射。
- many:如果应用于多对多关系,则应将此参数设置为 True。
class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.StringRelatedField(many=True) class Meta: model = Album fields = ['album_name', 'artist', 'tracks']# 序列化的数据表示形式{ 'album_name': 'Things We Lost In The Fire', 'artist': 'Low', 'tracks': [ '1: Sunflower', '2: Whitetail', '3: Dinosaur Act', ... ]}
PrimaryKeyRelatedField
字段通过逐渐表示关系目标。
- queryset:验证字段输入时用于模型实例查找的查询集,关系必须显式设置 queryset 或 read_only=True。
- many:如果应用于多对多关系,则应将此参数设置为 True。
- allow_null:如果设置为 True,则该字段将接受 None 可空关系的值或空字符串, 默认为 False。
- pk_field:设置为一个字段以控制主键值的序列化/反序列化,pk_field=UUIDField(format='hex') 。
class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True) class Meta: model = Album fields = ['album_name', 'artist', 'tracks']# 序列化的数据表示形式{ 'album_name': 'Undun', 'artist': 'The Roots', 'tracks': [ 89, 90, 91, ... ]}
HyperlinkedRelatedField
用于使用超链接的方式表示关系目标,需要一种确定使用哪些视图将需要超链接到模型实例的方法,默认情况下超链接应与匹配样式的视图名称通过 pk 关键字参数查找实例对象。
使用 extra_kwargs 设置中的 view_name 和 lookup_field 选项之一或全部覆盖 URL 字段视图名称和查找字段。
- view_name:用作关系目标的视图名称,使用的是标准路由器类则该字符串将为 <modelname>-detail。
- queryset:验证字段输入时用于模型实例查找的查询集,关系必须显式设置 queryset 或 read_only=True。
- many:应用于多对多关系,应将此参数设置为 True。
- allow_null:设置为 True则该字段将接受 None 可空关系的值或空字符串。
- lookup_field:目标上应用于查找的字段,应对应于引用视图上的 URL 关键字参数,默认值为 'pk'。
- lookup_url_kwarg:URL conf 中定义的关键字参数的名称,该参数与查找字段相对应,默认使用与相同的值 lookup_field。
- format:使用格式后缀则超链接字段将为目标使用相同的格式后缀。
class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.HyperlinkedRelatedField( many=True, read_only=True, view_name='track-detail' ) class Meta: model = Album fields = ['album_name', 'artist', 'tracks']# 序列化的数据表示形式{ 'album_name': 'Jession', 'artist': 'Paul', 'tracks': [ 'http://www.xxxx.com/api/data/45/', 'http://www.xxxx.com/api/data/46/', 'http://www.xxxx.com/api/data/47/', ... ]}
SlugRelatedField
使用目标上的字段表示关系目标。
- queryset:验证字段输入时用于模型实例查找的查询集,关系必须显式设置 queryset 或 read_only=True。
- many:应用于多对多关系则应将此参数设置为 True。
- allow_null:设置为 True 则该字段将接受 None 可空关系的值或空字符串。
class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.SlugRelatedField( many=True, read_only=True, slug_field='title' ) class Meta: model = Album fields = ['album_name', 'artist', 'tracks']# 序列化的数据表示形式{ 'album_name': 'Dear John', 'artist': 'Loney Dear', 'tracks': [ 'Airport Surroundings', 'Everything Turns to You', 'I Was Only Going Out', ... ]}
HyperlinkedIdentityField
可以作为标识关系应用,也可以用于对象的属性。
- view_name:用作关系目标的视图名称,使用的是标准路由器类则该字符串将为<modelname>-detail。
- lookup_field:目标上应用于查找的字段,应对应于引用视图上的 URL 关键字参数,默认值为 'pk'。
- lookup_url_kwarg:URL conf 中定义的关键字参数的名称,该参数与查找字段相对应,默认使用与相同的值 lookup_field。
- format:使用格式后缀则超链接字段将为目标使用相同的格式后缀。
class AlbumSerializer(serializers.HyperlinkedModelSerializer): track_listing = serializers.HyperlinkedIdentityField(view_name='track-list') class Meta: model = Album fields = ['album_name', 'artist', 'track_listing']# 序列化的数据表示形式{ 'album_name': 'The Eraser', 'artist': 'Thom Yorke', 'track_listing': 'http://www.example.com/api/track_list/12/',}
Nested relationships
嵌套关系应用。
class TrackSerializer(serializers.ModelSerializer): class Meta: model = Track fields = ['order', 'title', 'duration']class AlbumSerializer(serializers.ModelSerializer): tracks = TrackSerializer(many=True, read_only=True) class Meta: model = Album fields = ['album_name', 'artist', 'tracks']# 序列化的数据表示形式album = Album.objects.create(album_name="The Grey Album", artist='Danger Mouse')Track.objects.create(album=album, order=1, title='Public Service Announcement', duration=245)Track.objects.create(album=album, order=2, title='What More Can I Say', duration=264)Track.objects.create(album=album, order=3, title='Encore', duration=159)serializer = AlbumSerializer(instance=album)serializer.data{ 'album_name': 'The Grey Album', 'artist': 'Danger Mouse', 'tracks': [ {'order': 1, 'title': 'Public Service Announcement', 'duration': 245}, {'order': 2, 'title': 'What More Can I Say', 'duration': 264}, {'order': 3, 'title': 'Encore', 'duration': 159}, ... ],}
Writable nested serializers
可写的嵌套 serializer。嵌套 serializer 是只读的,如果要支持对嵌套序列化器字段的写操作, 则需要创建 create() 或 update() 方法, 以明确指定应如何保存子关系。
class TrackSerializer(serializers.ModelSerializer): class Meta: model = Track fields = ['order', 'title', 'duration']class AlbumSerializer(serializers.ModelSerializer): tracks = TrackSerializer(many=True) class Meta: model = Album fields = ['album_name', 'artist', 'tracks'] def create(self, validated_data): tracks_data = validated_data.pop('tracks') album = Album.objects.create(**validated_data) for track_data in tracks_data: Track.objects.create(album=album, **track_data) return album
序列化的数据表示形式。
data = { 'album_name': 'The Grey Album', 'artist': 'Danger Mouse', 'tracks': [ {'order': 1, 'title': 'Public Service Announcement', 'duration': 245}, {'order': 2, 'title': 'What More Can I Say', 'duration': 264}, {'order': 3, 'title': 'Encore', 'duration': 159}, ],}serializer = AlbumSerializer(data=data)serializer.is_valid()Trueserializer.save()<Album: Album object>
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除