serializer = CommentSerializer(data={'email':'foobar','content':'baz'})
serializer.is_valid()# False
serializer.errors
# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}
序列化器自定义字段级别的验证
from rest_framework import serializers
classBlogPostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
content = serializers.CharField()defvalidate_title(self, value):"""
Check that the blog post is about Django.
"""if'django'notin value.lower():raise serializers.ValidationError("Blog post is not about Django")return value
serializer = BlogPostSerializer(data={"title":"__title123","content":"__content123"})
serializer.is_valid()# False
serializer.errors
# {'title': [ErrorDetail(string='Blog post is not about Django', code='invalid')]}
自定义对象级别的验证
from rest_framework import serializers
classEventSerializer(serializers.Serializer):
description = serializers.CharField(max_length=100)
start = serializers.DateTimeField()
finish = serializers.DateTimeField()defvalidate(self, data):"""
Check that the start is before the stop.
"""if data['start']> data['finish']:raise serializers.ValidationError("finish must occur after start")return data
serializer = EventSerializer(data={"description":"描述","start":"2024-12-13 11:00:00","finish":"2024-12-11 11:00:00"})
serializer.is_valid()# False
serializer.errors
# {'non_field_errors': [ErrorDetail(string='finish must occur after start', code='invalid')]}
自定义单字段验证器
from rest_framework import serializers
defmultiple_of_ten(value):if value %10!=0:raise serializers.ValidationError('Not a multiple of ten')classGameRecord(serializers.Serializer):
score = serializers.IntegerField(validators=[multiple_of_ten])
serializer = GameRecord(data={"score":11})
serializer.is_valid()# False
serializer.errors
# {'score': [ErrorDetail(string='Not a multiple of ten', code='invalid')]}
访问初始数据和实例 (Accessing the initial data and instance)
from rest_framework import serializers
classCommentSerializer(serializers.Serializer):
user = UserSerializer(required=False)# May be an anonymous user.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
如果嵌套表示应该是项目列表,则应将 many = True 标志传递给嵌套的序列化器
from rest_framework import serializers
classCommentSerializer(serializers.Serializer):
user = UserSerializer(required=False)
edits = EditItemSerializer(many=True)# A nested list of 'edit' items.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
可写的嵌套表示 (Writable nested representations)
serializer = CommentSerializer(data={'user':{'email':'foobar','username':'doe'},'content':'baz'})
serializer.is_valid()# False
serializer.errors
# {'user': {'email': [u'Enter a valid e-mail address.']}, 'created': [u'This field is required.']}
重写create方法, 处理嵌套对象创建用户
from rest_framework import serializers
classUserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()classMeta:
model = User
fields =('username','email','profile')defcreate(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(user=user,**profile_data)return user
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):classMeta:
model = Account
fields =('id','account_name','users','created')
指定要包含的字段 (Specifying which fields to include)
fields显示的指定字段
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):classMeta:
model = Account
fields =('id','account_name','users','created')
fields显示所有字段
classAccountSerializer(serializers.ModelSerializer):classMeta:
model = Account
fields ='__all__'
exclude指定不显示的字段
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):classMeta:
model = Account
exclude =('users',)
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):classMeta:
model = Account
fields =('id','account_name','users','created')
depth =1
显式指定字段 (Specifying fields explicitly)
序列化器添加额外字段,或通过在类上声明字段来重写默认字段
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
groups = serializers.PrimaryKeyRelatedField(many=True)classMeta:
model = Account
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):classMeta:
model = Account
fields =('id','account_name','users','created')
read_only_fields =('account_name',)
只读字段是模型级别 unique_together 约束的一部分处理
from rest_framework import serializers
classAccountSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())classMeta:
model = Account
fields =('id','account_name','users','created')
from rest_framework import serializers
classCreateUserSerializer(serializers.ModelSerializer):classMeta:
model = User
fields =('email','username','password')
extra_kwargs ={'password':{'write_only':True}}defcreate(self, validated_data):
user = User(
email=validated_data['email'],
username=validated_data['username'])
user.set_password(validated_data['password'])
user.save()return user
from rest_framework import serializers
classAccountSerializer(serializers.HyperlinkedModelSerializer):classMeta:
model = Account
fields =('url','id','account_name','users','created')
from rest_framework import serializers
classBookListSerializer(serializers.ListSerializer):defcreate(self, validated_data):
books =[Book(**item)for item in validated_data]return Book.objects.bulk_create(books)classBookSerializer(serializers.Serializer):...classMeta:
list_serializer_class = BookListSerializer
自定义多个更新 (Customizing multiple update)
默认隐式生成的 id 字段被标记为 read_only, 需要向实例序列化器显式添加 id 字段,才可以使用
from rest_framework import serializers
classBookListSerializer(serializers.ListSerializer):defupdate(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 isNone:
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 notin data_mapping:
book.delete()return ret
classBookSerializer(serializers.Serializer):# 我们需要使用主键识别列表中的元素,# 所以在这里使用一个可写字段,而不是默认的只读字段。id= serializers.IntegerField()...classMeta:
list_serializer_class = BookListSerializer
BaseSerializer
BaseSerialAlgisher 类,可以用来方便地支持可选的序列化和反序列化样式
BaseSerializer 类不会在可浏览的 API 中生成 HTML 表单, 返回的数据不包括允许每个字段被渲染成合适的 HTML 输入的所有字段信息
from rest_framework import serializers
classHighScoreSerializer(serializers.BaseSerializer):defto_internal_value(self, data):
score = data.get('score')
player_name = data.get('player_name')# 执行数据验证。ifnot score:raise serializers.ValidationError({'score':'This field is required.'})ifnot player_name:raise serializers.ValidationError({'player_name':'This field is required.'})iflen(player_name)>10:raise serializers.ValidationError({'player_name':'May not be more than 10 characters.'})# 返回验证值。这将作为可用的 `.validated_data` 属性。return{'score':int(score),'player_name': player_name
}defto_representation(self, obj):return{'score': obj.score,'player_name': obj.player_name
}defcreate(self, validated_data):return HighScore.objects.create(**validated_data)
创建新的基类 (Creating new base classes)
处理将任意对象强制转换为基本表示的通用序列化器
from rest_framework import serializers
classObjectSerializer(serializers.BaseSerializer):"""
任意复杂对象强制转换为原始表示的只读序列化器。
"""defto_representation(self, obj):for attribute_name indir(obj):
attribute =getattr(obj, attribute_name)if attribute_name('_'):# 忽略私有属性。passelifhasattr(attribute,'__call__'):# 忽略方法和其他 callables。passelifisinstance(attribute,(str,int,bool,float,type(None))):# 原始类型可以通过未修改的方式传递。
output[attribute_name]= attribute
elifisinstance(attribute,list):# 递归处理列表中的项。
output[attribute_name]=[
self.to_representation(item)for item in attribute
]elifisinstance(attribute,dict):# 递归处理字典中的项。
output[attribute_name]={str(key): self.to_representation(value)for key, value in attribute.items()}else:# 将其他内容强制到其字符串表示形式。
output[attribute_name]=str(attribute)
高级序列化器用法 (Advanced serializer usage)
重写序列化和反序列化行为 (Overriding serialization and deserialization behavior)
转换用户名为小写
from rest_framework import serializers
classObjectSerializer(serializers.BaseSerializer):defto_representation(self, instance):"""Convert `username` to lowercase."""
ret =super().to_representation(instance)
ret['username']= ret['username'].lower()return ret
序列化器继承 (Serializer Inheritance)
from rest_framework.serializers import ModelSerializer
classMyBaseSerializer(ModelSerializer):
my_field = serializers.CharField()classMySerializer(MyBaseSerializer):
my_field =None