制作企业网站怎么做,网站英文域名是什么,wordpress添加微信微博等小工具,教我做网站Django drf 序列化器 
序列化器 扩展serializers的有用性是我们想要解决的问题。但是#xff0c;这不是一个微不足道的问题#xff0c;而是需要一些严肃的设计工作。— Russell Keith-Magee, Django用户组 序列化器允许把像查询集和模型实例这样的复杂数据转换为可以轻松渲染…Django drf 序列化器 
序列化器 
扩展serializers的有用性是我们想要解决的问题。但是这不是一个微不足道的问题而是需要一些严肃的设计工作。— Russell Keith-Magee, Django用户组 序列化器允许把像查询集和模型实例这样的复杂数据转换为可以轻松渲染成JSONXML或其他内容类型的原生Python类型。序列化器还提供反序列化在验证传入的数据之后允许解析数据转换回复杂类型。 
REST framework中的serializers与Django的Form和ModelForm类非常像。我们提供了一个Serializer类它为你提供了强大的通用方法来控制响应的输出以及一个ModelSerializer类它为创建用于处理模型实例和查询集的序列化程序提供了有用的快捷实现方式。 
附加:源码分析 
序列化组件先调用__new__方法如果manyTrue生成ListSerializer对象如果为False生成Serializer对象
序列化对象.data方法--调用父类data方法---调用对象自己的to_representation自定义的序列化类无此方法去父类找
Aerializer类里有to_representation方法for循环执行attribute  field.get_attribute(instance)
再去Field类里去找get_attribute方法self.source_attrs就是被切分的source然后执行get_attribute方法source_attrs
当参数传过去判断是方法就加括号执行是属性就把值取出来 
声明序列化器 
让我们从创建一个简单的对象开始我们可以使用下面的例子 
from datetime import datetimeclass Comment(object):def __init__(self, email, content, createdNone):self.email  emailself.content  contentself.created  created or datetime.now()comment  Comment(emailleilaexample.com, contentfoo bar) 
我们将声明一个序列化器我们可以使用它来序列化和反序列化与Comment对象相应的数据。 
声明一个序列化器看起来非常像声明一个form 
from rest_framework import serializersclass CommentSerializer(serializers.Serializer):email  serializers.EmailField()content  serializers.CharField(max_length200)created  serializers.DateTimeField() 
序列化对象 
我们现在可以用CommentSerializer去序列化一个comment或comment列表。同样使用Serializer类看起来很像使用Form类。 
serializer  CommentSerializer(comment)
serializer.data
# {email: leilaexample.com, content: foo bar, created: 2016-01-27T15:17:10.375877} 
此时我们将模型实例转换为Python原生的数据类型。为了完成序列化过程我们将数据转化为json。 
from rest_framework.renderers import JSONRendererjson  JSONRenderer().render(serializer.data)
json
# b{email:leilaexample.com,content:foo bar,created:2016-01-27T15:17:10.375877} 
反序列化对象 
反序列化是类似的。首先我们将一个流解析为Python原生的数据类型... 
from django.utils.six import BytesIO
from rest_framework.parsers import JSONParserstream  BytesIO(json)
data  JSONParser().parse(stream) 
...然后我们将这些原生数据类型恢复到已验证数据的字典中。 
serializer  CommentSerializer(datadata)
serializer.is_valid()
# True
serializer.validated_data
# {content: foo bar, email: leilaexample.com, created: datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)} 
保存实例 
如果我们希望能够返回基于验证数据的完整对象实例我们需要实现其中一个或全部实现.create()和update()方法。例如 
class CommentSerializer(serializers.Serializer):email  serializers.EmailField()content  serializers.CharField(max_length200)created  serializers.DateTimeField()def create(self, validated_data):return Comment(**validated_data)def update(self, instance, validated_data):instance.email  validated_data.get(email, instance.email)instance.content  validated_data.get(content, instance.content)instance.created  validated_data.get(created, instance.created)return instance 
如果你的对象实例对应Django的模型你还需要确保这些方法将对象保存到数据库。例如如果Comment是一个Django模型的话具体的方法可能如下所示 def create(self, validated_data):return Comment.objects.create(**validated_data)def update(self, instance, validated_data):instance.email  validated_data.get(email, instance.email)instance.content  validated_data.get(content, instance.content)instance.created  validated_data.get(created, instance.created)instance.save()return instance 
现在当我们反序列化数据的时候基于验证过的数据我们可以调用.save()方法返回一个对象实例。 
comment  serializer.save() 
调用.save()方法将创建新实例或者更新现有实例具体取决于实例化序列化器类的时候是否传递了现有实例 
# .save() will create a new instance.
serializer  CommentSerializer(datadata)# .save() will update the existing comment instance.
serializer  CommentSerializer(comment, datadata) 
.create()和.update()方法都是可选的。你可以根据你序列化器类的用例不实现、实现它们之一或都实现。 
传递附加属性到.save() 
有时你会希望你的视图代码能够在保存实例时注入额外的数据。此额外数据可能包括当前用户当前时间或不是请求数据一部分的其他信息。 
你可以通过在调用.save()时添加其他关键字参数来执行此操作。例如 
serializer.save(ownerrequest.user) 
在.create()或.update()被调用时任何其他关键字参数将被包含在validated_data参数中。 
直接重写.save() 
在某些情况下.create()和.update()方法可能无意义。例如在contact form中我们可能不会创建新的实例而是发送电子邮件或其他消息。 
在这些情况下你可以选择直接重写.save()方法因为那样更可读和有意义。 
例如 
class ContactForm(serializers.Serializer):email  serializers.EmailField()message  serializers.CharField()def save(self):email  self.validated_data[email]message  self.validated_data[message]send_email(fromemail, messagemessage) 
请注意在上述情况下我们现在不得不直接访问serializer的.validated_data属性。 
验证 
反序列化数据的时候你始终需要先调用is_valid()方法然后再尝试去访问经过验证的数据或保存对象实例。如果发生任何验证错误.errors属性将包含表示生成的错误消息的字典。例如 
serializer  CommentSerializer(data{email: foobar, content: baz})
serializer.is_valid()
# False
serializer.errors
# {email: [uEnter a valid e-mail address.], created: [uThis field is required.]} 
字典里的每一个键都是字段名称值是与该字段对应的任何错误消息的字符串列表。non_field_errors键可能存在它将列出任何一般验证错误信息。non_field_errors的名称可以通过REST framework设置中的NON_FIELD_ERRORS_KEY来自定义。 当对对象列表进行序列化时返回的错误是每个反序列化项的字典列表。 
抛出无效数据的异常 
.is_valid()方法使用可选的raise_exception标志如果存在验证错误将会抛出一个serializers.ValidationError异常。 
这些异常由REST framework提供的默认异常处理程序自动处理默认情况下将返回HTTP 400 Bad Request响应。 
# 如果数据无效就返回400响应
serializer.is_valid(raise_exceptionTrue) 
字段级别的验证 
你可以通过向你的Serializer子类中添加.validate_field_name方法来指定自定义字段级别的验证。这些类似于Django表单中的.clean_field_name方法。 
这些方法采用单个参数即需要验证的字段值。 
你的validate_field_name方法应该返回一个验证过的数据或者抛出一个serializers.ValidationError异常。例如 
from rest_framework import serializersclass BlogPostSerializer(serializers.Serializer):title  serializers.CharField(max_length100)content  serializers.CharField()def validate_title(self, value):Check that the blog post is about Django.if django not in value.lower():raise serializers.ValidationError(Blog post is not about Django)return value 
注意 如果你在序列化器中声明field_name的时候带有requiredFalse参数字段不被包含的时候这个验证步骤就不会执行。 
对象级别的验证 
要执行需要访问多个字段的任何其他验证请添加一个.validate()方法到你的Serializer子类中。这个方法采用字段值字典的单个参数如果需要应该抛出一个 ValidationError异常或者只是返回经过验证的值。例如 
from rest_framework import serializersclass EventSerializer(serializers.Serializer):description  serializers.CharField(max_length100)start  serializers.DateTimeField()finish  serializers.DateTimeField()def validate(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 
验证器 
序列化器上的各个字段都可以包含验证器通过在字段实例上声明例如 
def multiple_of_ten(value):if value % 10 ! 0:raise serializers.ValidationError(Not a multiple of ten)class GameRecord(serializers.Serializer):score  IntegerField(validators[multiple_of_ten])... 
序列化器类还可以包括应用于一组字段数据的可重用的验证器。这些验证器要在内部的Meta类中声明如下所示 
class EventSerializer(serializers.Serializer):name  serializers.CharField()room_number  serializers.IntegerField(choices[101, 102, 103, 201])date  serializers.DateField()class Meta:# 每间屋子每天只能有1个活动。validators  UniqueTogetherValidator(querysetToDoItem.objects.all(),fields[room_number, date]) 
更多信息请参阅 validators文档。 
访问初始数据和实例 
将初始化对象或者查询集传递给序列化实例时可以通过.instance访问。如果没有传递初始化对象那么.instance属性将是None。 
将数据传递给序列化器实例时未修改的数据可以通过.initial_data获取。如果没有传递data关键字参数那么.initial_data属性就不存在。 
部分更新 
默认情况下序列化器必须传递所有必填字段的值否则就会引发验证错误。你可以使用 partial参数来允许部分更新。 
# 使用部分数据更新comment 
serializer  CommentSerializer(comment, data{content: ufoo bar}, partialTrue) 
处理嵌套对象 
前面的实例适用于处理只有简单数据类型的对象但是有时候我们也需要表示更复杂的对象其中对象的某些属性可能不是字符串、日期、整数这样简单的数据类型。 
Serializer类本身也是一种Field并且可以用来表示一个对象类型嵌套在另一个对象中的关系。 
class UserSerializer(serializers.Serializer):email  serializers.EmailField()username  serializers.CharField(max_length100)class CommentSerializer(serializers.Serializer):user  UserSerializer()content  serializers.CharField(max_length200)created  serializers.DateTimeField() 
如果嵌套表示可以接收 None值则应该将 requiredFalse标志传递给嵌套的序列化器。 
class CommentSerializer(serializers.Serializer):user  UserSerializer(requiredFalse)  # 可能是匿名用户。content  serializers.CharField(max_length200)created  serializers.DateTimeField() 
类似的如果嵌套的关联字段可以接收一个列表那么应该将manyTrue标志传递给嵌套的序列化器。 
class CommentSerializer(serializers.Serializer):user  UserSerializer(requiredFalse)edits  EditItemSerializer(manyTrue)  # edit项的嵌套列表content  serializers.CharField(max_length200)created  serializers.DateTimeField() 
可写的嵌套表示 
当处理支持反序列化数据的嵌套表示时嵌套对象的任何错误都嵌套在嵌套对象的字段名下。 
serializer  CommentSerializer(data{user: {email: foobar, username: doe}, content: baz})
serializer.is_valid()
# False
serializer.errors
# {user: {email: [uEnter a valid e-mail address.]}, created: [uThis field is required.]} 
类似的.validated_data 属性将包括嵌套数据结构。 
为嵌套关系定义.create()方法 
如果你支持可写的嵌套表示则需要编写.create()或.update()处理保存多个对象的方法。 
下面的示例演示如何处理创建一个具有嵌套的概要信息对象的用户。 
class UserSerializer(serializers.ModelSerializer):profile  ProfileSerializer()class Meta:model  Userfields  (username, email, profile)def create(self, validated_data):profile_data  validated_data.pop(profile)user  User.objects.create(**validated_data)Profile.objects.create(useruser, **profile_data)return user 
为嵌套关系定义.update()方法 
对于更新你需要仔细考虑如何处理关联字段的更新。 例如如果关联字段的值是None或者没有提供那么会发生下面哪一项 
在数据库中将关联字段设置成NULL。删除关联的实例。忽略数据并保留这个实例。抛出验证错误。 
下面是我们之前UserSerializer类中update()方法的一个例子。 def update(self, instance, validated_data):profile_data  validated_data.pop(profile)# 除非应用程序正确执行# 保证这个字段一直被设置# 否则就应该抛出一个需要处理的DoesNotExist。profile  instance.profileinstance.username  validated_data.get(username, instance.username)instance.email  validated_data.get(email, instance.email)instance.save()profile.is_premium_member  profile_data.get(is_premium_member,profile.is_premium_member)profile.has_support_contract  profile_data.get(has_support_contract,profile.has_support_contract)profile.save()return instance 
因为嵌套关系的创建和更新行为可能不明确并且可能需要关联模型间的复杂依赖关系REST framework 3 要求你始终明确的定义这些方法。默认的ModelSerializer .create()和.update()方法不包括对可写嵌套关联的支持。 
提供自动支持某种类型的自动写入嵌套关联的第三方包可能与3.1版本一同放出。 
处理在模型管理类中保存关联实例 
在序列化器中保存多个相关实例的另一种方法是编写处理创建正确实例的自定义模型管理器类。 
例如假设我们想确保User实例和Profile实例总是作为一对一起创建。我们可能会写一个类似这样的自定义管理器类 
class UserManager(models.Manager):...def create(self, username, email, is_premium_memberFalse, has_support_contractFalse):user  User(usernameusername, emailemail)user.save()profile  Profile(useruser,is_premium_memberis_premium_member,has_support_contracthas_support_contract)profile.save()return user 
这个管理器类现在更好的封装了用户实例和用户信息实例总是在同一时间创建。我们在序列化器类上的.create()方法现在能够用新的管理器方法重写。 
def create(self, validated_data):return User.objects.create(usernamevalidated_data[username],emailvalidated_data[email]is_premium_membervalidated_data[profile][is_premium_member]has_support_contractvalidated_data[profile][has_support_contract]) 
有关此方法的更多详细信息请参阅Django文档中的 模型管理器和使用模型和管理器类的相关博客。 
处理多个对象 
Serializer类还可以序列化或反序列化对象的列表。 
序列化多个对象 
为了能够序列化一个查询集或者一个对象列表而不是一个单独的对象应该在实例化序列化器类的时候传一个manyTrue参数。这样就能序列化一个查询集或一个对象列表。 
queryset  Book.objects.all()
serializer  BookSerializer(queryset, manyTrue)
serializer.data
# [
#     {id: 0, title: The electric kool-aid acid test, author: Tom Wolfe},
#     {id: 1, title: If this is a man, author: Primo Levi},
#     {id: 2, title: The wind-up bird chronicle, author: Haruki Murakami}
# ] 
反序列化多个对象 
反序列化多个对象默认支持多个对象的创建但是不支持多个对象的更新。有关如何支持或自定义这些情况的更多信息请查阅这个文档ListSerializer。 
包括额外的上下文 
在某些情况下除了要序列化的对象之外还需要为序列化程序提供额外的上下文。一个常见的情况是如果你使用包含超链接关系的序列化程序这需要序列化器能够访问当前的请求以便正确生成完全限定的URL。 
你可以在实例化序列化器的时候传递一个context参数来传递任意的附加上下文。例如 
serializer  AccountSerializer(account, context{request: request})
serializer.data
# {id: 6, owner: udenvercoder9, created: datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), details: http://example.com/accounts/6/details} 
这个上下文的字典可以在任何序列化器字段的逻辑中使用例如.to_representation()方法中可以通过访问self.context属性获取上下文字典。 
ModelSerializer 
通常你会想要与Django模型相对应的序列化类。 
ModelSerializer类能够让你自动创建一个具有模型中相应字段的Serializer类。 
这个ModelSerializer类和常规的Serializer类一样不同的是 
它根据模型自动生成一组字段。它自动生成序列化器的验证器比如unique_together验证器。它默认简单实现了.create()方法和.update()方法。 
声明一个ModelSerializer如下 
class AccountSerializer(serializers.ModelSerializer):class Meta:model  Accountfields  (id, account_name, users, created) 
默认情况下所有的模型的字段都将映射到序列化器上相应的字段。 
模型中任何关联字段比如外键都将映射到PrimaryKeyRelatedField字段。默认情况下不包括反向关联除非像serializer relations文档中规定的那样显式包含。 
检查ModelSerializer 
序列化类生成有用的详细表示字符串允许你全面检查其字段的状态。 这在使用ModelSerializers时特别有用因为你想确定自动创建了哪些字段和验证器。 
要检查的话打开Django shell,执行 python manage.py shell然后导入序列化器类实例化它并打印对象的表示 from myapp.serializers import AccountSerializerserializer  AccountSerializer()print(repr(serializer))
AccountSerializer():id  IntegerField(labelID, read_onlyTrue)name  CharField(allow_blankTrue, max_length100, requiredFalse)owner  PrimaryKeyRelatedField(querysetUser.objects.all()) 
指定要包括的字段 
如果你希望在模型序列化器中使用默认字段的一部分你可以使用fields或exclude选项来执行此操作就像使用ModelForm一样。强烈建议你使用fields属性显式的设置要序列化的字段。这样就不太可能因为你修改了模型而无意中暴露了数据。 
例如 
class AccountSerializer(serializers.ModelSerializer):class Meta:model  Accountfields  (id, account_name, users, created) 
你还可以将fields属性设置成__all__来表明使用模型中的所有字段。 
例如 
class AccountSerializer(serializers.ModelSerializer):class Meta:model  Accountfields  __all__ 
你可以将exclude属性设置成一个从序列化器中排除的字段列表。 
例如 
class AccountSerializer(serializers.ModelSerializer):class Meta:model  Accountexclude  (users,) 
在上面的例子中如果Account模型有三个字段account_nameusers和created那么只有 account_name和created会被序列化。 
在fields和exclude属性中的名称通常会映射到模型类中的模型字段。 
或者fields选项中的名称可以映射到模型类中不存在任何参数的属性或方法。 
指定嵌套序列化 
默认ModelSerializer使用主键进行关联但是你也可以使用depth选项轻松生成嵌套关联 
class AccountSerializer(serializers.ModelSerializer):class Meta:model  Accountfields  (id, account_name, users, created)depth  1 
depth选项应该设置一个整数值表明应该遍历的关联深度。 
如果要自定义序列化的方式你需要自定义该子段。 
明确指定字段 
你可以通过在ModelSerializer类上声明字段来增加额外的字段或者重写默认的字段就和在Serializer类一样的。 
class AccountSerializer(serializers.ModelSerializer):url  serializers.CharField(sourceget_absolute_url, read_onlyTrue)groups  serializers.PrimaryKeyRelatedField(manyTrue)class Meta:model  Account 
额外的字段可以对应模型上任何属性或可调用的方法。 
指定只读字段 
你可能希望将多个字段指定为只读而不是显式的为每个字段添加read_onlyTrue属性这种情况你可以使用Meta的read_only_fields选项。 
该选项应该是字段名称的列表或元祖并像下面这样声明 
class AccountSerializer(serializers.ModelSerializer):class Meta:model  Accountfields  (id, account_name, users, created)read_only_fields  (account_name,) 
模型中已经设置editableFalse的字段和默认就被设置为只读的AutoField字段都不需要添加到read_only_fields选项中。 
注意: 有一种特殊情况其中一个只读字段是模型级别unique_together约束的一部分。在这种情况下序列化器类需要该字段才能验证约束但也不能由用户编辑。 
处理此问题的正确方法是在序列化器上显式指定该字段同时提供read_onlyTrue和default…关键字参数。 
这种情况的一个例子就是对于一个和其他标识符unique_together的当前认证的User是只读的。 在这种情况下你可以像下面这样声明user字段 
user  serializers.PrimaryKeyRelatedField(read_onlyTrue, defaultserializers.CurrentUserDefault()) 
有关UniqueTogetherValidator和CurrentUserDefault类的详细文档请查阅验证器的文档。 
附加关键字参数 
还可以通过使用extra_kwargs选项快捷地在字段上指定任意附加的关键字参数。在read_only_fields这种情况下你不需要在序列化器上式的声明该字段。 
这个选项是一个将具体字段名称当作键值的字典。例如 
class CreateUserSerializer(serializers.ModelSerializer):class Meta:model  Userfields  (email, username, password)extra_kwargs  {password: {write_only: True}}def create(self, validated_data):user  User(emailvalidated_data[email],usernamevalidated_data[username])user.set_password(validated_data[password])user.save()return user 
关联字段 
在序列化模型实例的时候你可以选择多种不同的方式来表示关联关系。对于ModelSerializer默认是使用相关实例的主键。 
替代的其他方法包括使用超链接序列化序列化完整的嵌套表示或者使用自定义表示的序列化。 
更多详细信息请查阅serializer relations文档。 
自定义字段映射 
ModelSerializer类还公开了一个可以覆盖的API以便在实例化序列化器时改变序列化器字段的自动确定。 
通常情况下如果ModelSerializer没有生成默认情况下你需要的字段那么你应该将它们显式地添加到类中或者直接使用常规的Serializer类。但是在某些情况下你可能需要创建一个新的基类来定义给任意模型创建序列化字段的方式。 
.serializer_field_mapping 
将Django model类映射到REST framework serializer类。你可以覆写这个映射来更改每个模型应该使用的默认序列化器类。 
.serializer_related_field 
这个属性应是序列化器字段类默认情况下用于关联字段。 
对于ModelSerializer此属性默认是PrimaryKeyRelatedField。 
对于HyperlinkedModelSerializer此属性默认是serializers.HyperlinkedRelatedField。 
serializer_url_field 
应该用于序列化器上任何url字段的序列化器字段类。 
默认是 serializers.HyperlinkedIdentityField 
serializer_choice_field 
应用于序列化器上任何选择字段的序列化器字段类。 
默认是serializers.ChoiceField 
The field_class和field_kwargs API 
调用下面的方法来确定应该自动包含在序列化器类中每个字段的类和关键字参数。这些方法都应该返回两个 (field_class, field_kwargs)元祖。 
.build_standard_field(self, field_name, model_field) 
调用后生成对应标准模型字段的序列化器字段。 
默认实现是根据serializer_field_mapping属性返回一个序列化器类。 
.build_relational_field(self, field_name, relation_info) 
调用后生成对应关联模型字段的序列化器字段。 
默认实现是根据serializer_relational_field属性返回一个序列化器类。 
这里的relation_info参数是一个命名元祖包含model_fieldrelated_modelto_many和has_through_model属性。 
.build_nested_field(self, field_name, relation_info, nested_depth) 
当depth选项被设置时被调用后生成一个对应到关联模型字段的序列化器字段。 
默认实现是动态的创建一个基于ModelSerializer或HyperlinkedModelSerializer的嵌套的序列化器类。 
nested_depth的值是depth的值减1。 
relation_info参数是一个命名元祖包含 model_fieldrelated_modelto_many和has_through_model属性。 
.build_property_field(self, field_name, model_class) 
被调用后生成一个对应到模型类中属性或无参数方法的序列化器字段。 
默认实现是返回一个ReadOnlyField类。 
.build_url_field(self, field_name, model_class) 
被调用后为序列化器自己的url字段生成一个序列化器字段。默认实现是返回一个HyperlinkedIdentityField类。 
.build_unknown_field(self, field_name, model_class) 
当字段名称没有对应到任何模型字段或者模型属性时调用。 默认实现会抛出一个错误尽管子类可能会自定义该行为。 
HyperlinkedModelSerializer 
HyperlinkedModelSerializer类类似于ModelSerializer类不同之处在于它使用超链接来表示关联关系而不是主键。 
默认情况下序列化器将包含一个url字段而不是主键字段。 
url字段将使用HyperlinkedIdentityField字段来表示模型的任何关联都将使用HyperlinkedRelatedField字段来表示。 
你可以通过将主键添加到fields选项中来显式的包含例如 
class AccountSerializer(serializers.HyperlinkedModelSerializer):class Meta:model  Accountfields  (url, id, account_name, users, created) 
绝对和相对URL 
当实例化一个HyperlinkedModelSerializer时你必须在序列化器的上下文中包含当前的request值例如 
serializer  AccountSerializer(queryset, context{request: request}) 
这样做将确保超链接可以包含恰当的主机名一边生成完全限定的URL例如 
http://api.example.com/accounts/1/ 
而不是相对的URL例如 
/accounts/1/ 
如果你真的要使用相对URL你应该明确的在序列化器上下文中传递一个{request: None}。 
如何确定超链接视图 
需要一种确定哪些视图能应用超链接到模型实例的方法。 
默认情况下超链接期望对应到一个样式能匹配{model_name}-detail的视图并通过pk关键字参数查找实例。 
你可以通过在extra_kwargs中设置view_name和lookup_field中的一个或两个来重写URL字段视图名称和查询字段。如下所示 
class AccountSerializer(serializers.HyperlinkedModelSerializer):class Meta:model  Accountfields  (account_url, account_name, users, created)extra_kwargs  {url: {view_name: accounts, lookup_field: account_name},users: {lookup_field: username}} 
或者你可以显式的设置序列化器上的字段。例如 
class AccountSerializer(serializers.HyperlinkedModelSerializer):url  serializers.HyperlinkedIdentityField(view_nameaccounts,lookup_fieldslug)users  serializers.HyperlinkedRelatedField(view_nameuser-detail,lookup_fieldusername,manyTrue,read_onlyTrue)class Meta:model  Accountfields  (url, account_name, users, created) 
提示正确匹配超链接表示和你的URL配置有时可能会有点困难。打印一个HyperlinkedModelSerializer实例的repr是一个特别有用的方式来检查关联关系映射的那些视图名称和查询字段。 
更改URL字段名称 
URL字段的名称默认为url。你可以通过使用URL_FIELD_NAME设置进行全局性修改。 
ListSerializer 
ListSerializer类能够序列化和一次验证多个对象。你通常不需要直接使用ListSerializer而是应该在实例化一个序列化器时简单地传递一个manyTrue参数。 
当一个序列化器在带有manyTrue选项被序列化时将创建一个ListSerializer实例。该序列化器类将成为ListSerializer类的子类。 
下面的参数也可以传递给ListSerializer字段或者一个带有manyTrue参数的序列化器。 
allow_empty 
默认是True但是如果你不想把空列表当作有效输入的话可以把它设置成False。 
自定义ListSerializer行为 
下面是你可能希望要定制ListSerializer行为的一些情况。例如 
你希望提供列表的特定验证例如检查一个元素是否与列表中的另外一个元素冲突。你要自定义多个对象的创建或更新行为。 
对于这些情况当你可以通过使用序列化器类的Meta类下面的list_serializer_class选项来修改当manyTrue时正在使用的类。 
例如 
class CustomListSerializer(serializers.ListSerializer):...class CustomSerializer(serializers.Serializer):...class Meta:list_serializer_class  CustomListSerializer 
自定义多个对象的创建 
多个对象的创建默认实现是简单地调用列表中每个对象的.create()方法。如果要自定义实现那么你需要自定义当被传递manyTrue参数时使用的ListSerializer类中的.create()方法。 
例如 
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 
自定义多对象的更新 
默认情况下ListSerializer类不支持多对象的更新。这是因为插入和删除的预期行为是不明确的。 
要支持多对象更新的话你需要自己明确地实现。编写多个对象更新的代码时要注意以下几点 
如何确定数据列表中的每个元素应该对应更新哪个实例如何处理插入它们是无效的还是创建新对象移除应该如何处理它们是要删除对象还是删除关联关系它们应该被忽略还是提示无效操作排序如何处理改变两个元素的位置是否意味着任何状态改变或者应该被忽视 
你需要向实例序列化器中显式添加一个id字段。默认隐式生成的id字段是read_only。这就导致它在更新时被删除。一旦你明确地声明它它将在列表序列化器的update方法中可用。 
下面是一个你可以选择用来做多个对象更新的示例 
class BookListSerializer(serializers.ListSerializer):def update(self, instance, validated_data):# Maps for id-instance and id-data item.book_mapping  {book.id: book for book in instance}data_mapping  {item[id]: item for item in validated_data}# Perform creations and updates.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))# Perform deletions.for book_id, book in book_mapping.items():if book_id not in data_mapping:book.delete()return retclass BookSerializer(serializers.Serializer):# 我们需要使用主键来识别列表中的元素# 所以在这里使用可写的字段而不是默认的只读字段。id  serializers.IntegerField()...id  serializers.IntegerField(requiredFalse)class Meta:list_serializer_class  BookListSerializer 
类似于REST framework 2中allow_add_remove的自动支持多个对象更新操作可能会在3.1版本的第三方包中提供。 
自定义ListSerializer初始化 
当带有manyTrue参数的序列化器被实例化时我们需要确定哪些参数和关键字参数应该被传递给子类Serializer和父类ListSerializer的.__init__()方法。 
默认实现是将所有参数都传递给两个类出了validators和任何关键字参数。这两个参数都假定用于子序列化器类。 
偶尔你可能需要明确指定当被传递manyTrue参数时子类和父类应该如何实例化。你可以使用many_init类方法来执行此操作。 classmethoddef many_init(cls, *args, **kwargs):# 实例化子序列化器类。kwargs[child]  cls()# 实例化列表序列化父类return CustomListSerializer(*args, **kwargs) 
BaseSerializer 
BaseSerializer 可以很简单的用来替代序列化和反序列化的样式。 
该类实现与Serializer类相同的基本API 
.data - 返回传出的原始数据。.is_valid() - 反序列化并验证传入的数据。.validated_data - 返回经过验证后的传入数据。.errors - 返回验证期间的错误。.save() - 将验证的数据保留到对象实例中。 
它还有可以覆写的四种方法具体取决于你想要序列化类支持的功能 
.to_representation() - 重写此方法来改变读取操作的序列化结果。.to_internal_value() - 重写此方法来改变写入操作的序列化结果。.create() 和 .update() - 重写其中一个或两个来改变保存实例时的动作。 
因为此类提供与Serializer类相同的接口所以你可以将它与现有的基于类的通用视图一起使用就像使用常规Serializer或ModelSerializer一样。 
这样做时你需要注意到的唯一区别是BaseSerializer类并不会在可浏览的API页面中生成HTML表单。 
只读的 BaseSerializer classes 
要使用BaseSerializer类实现只读序列化程序我们只需要覆写.to_representation()方法。让我们看一个简单的Django模型的示例 
class HighScore(models.Model):created  models.DateTimeField(auto_now_addTrue)player_name  models.CharField(max_length10)score  models.IntegerField() 
创建一个只读的序列化程序来将HighScore实例转换为原始数据类型非常简单。 
class HighScoreSerializer(serializers.BaseSerializer):def to_representation(self, obj):return {score: obj.score,player_name: obj.player_name} 
我们现在可以使用这个类来序列化单个HighScore实例 
api_view([GET])
def high_score(request, pk):instance  HighScore.objects.get(pkpk)serializer  HighScoreSerializer(instance)return Response(serializer.data) 
或者使用它来序列化多个实例 
api_view([GET])
def all_high_scores(request):queryset  HighScore.objects.order_by(-score)serializer  HighScoreSerializer(queryset, manyTrue)return Response(serializer.data) 
Read-write BaseSerializer classes 
要创建一个读写都支持的序列化器我们首先需要实现.to_internal_value()方法。这个方法返回用来构造对象实例的经过验证的值如果提供的数据格式不正确则可能引发ValidationError。 
一旦你实现了.to_internal_value()方法那些基础的验证API都会在序列化对象上可用了你就可以使用.is_valid(), .validated_data 和 .errors 方法。 
如果你还想支持.save()你还需要实现.create()和.update()方法中的一个或两个。 
下面就是完整版的支持读、写操作的 HighScoreSerializer 完整示例了。 
class HighScoreSerializer(serializers.BaseSerializer):def to_internal_value(self, data):score  data.get(score)player_name  data.get(player_name)# 执行数据有效性校验if not score:raise ValidationError({score: This field is required.})if not player_name:raise ValidationError({player_name: This field is required.})if len(player_name)  10:raise ValidationError({player_name: May not be more than 10 characters.})# 返回通过验证的数据 这用来作为 .validated_data 属性的值。return {score: int(score),player_name: player_name}def to_representation(self, obj):return {score: obj.score,player_name: obj.player_name}def create(self, validated_data):return HighScore.objects.create(**validated_data) 
创建一个新的基类 
BaseSerializer类还可以用来创建新的通用序列化程序基类来处理特定的序列化样式或者用来整合备用存储后端。 
下面这个类是一个可以将任意对象强制转换为基本表示的通用序列化程序的示例。 
class ObjectSerializer(serializers.BaseSerializer):一个只读序列化程序它将任意复杂的对象强制转换为内置数据类型表示。def to_representation(self, obj):for attribute_name in dir(obj):attribute  getattr(obj, attribute_name)if attribute_name(_):# 忽略私有属性passelif hasattr(attribute, __call__):# 忽略方法和其他可调用对象passelif isinstance(attribute, (str, int, bool, float, type(None))):# 内置的原始数据类型不做修改output[attribute_name]  attributeelif isinstance(attribute, list):# 递归处理列表中的对象output[attribute_name]  [self.to_representation(item) for item in attribute]elif isinstance(attribute, dict):# 递归处理字典中的对象output[attribute_name]  {str(key): self.to_representation(value)for key, value in attribute.items()}else:# 将其他数据类型强制转换为字符串表示output[attribute_name]  str(attribute) 
扩展:  rest-framework序列化之Serializer 
models部分: from django.db import models# Create your models here.class Book(models.Model):titlemodels.CharField(max_length32)pricemodels.IntegerField()pub_datemodels.DateField()publishmodels.ForeignKey(Publish)authorsmodels.ManyToManyField(Author)def __str__(self):return self.titleclass Publish(models.Model):namemodels.CharField(max_length32)emailmodels.EmailField()def __str__(self):return self.nameclass Author(models.Model):namemodels.CharField(max_length32)agemodels.IntegerField()def __str__(self):return self.name view部分 from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializersfrom rest_framework import serializersclass BookSerializers(serializers.Serializer):titleserializers.CharField(max_length32)priceserializers.IntegerField()pub_dateserializers.DateField()publishserializers.CharField(sourcepublish.name)#authorsserializers.CharField(sourceauthors.all)authorsserializers.SerializerMethodField() # 自定义显示def get_authors(self,obj):temp[]for author in obj.authors.all():temp.append(author.name)return temp#此处可以继续用author的Serializers# def get_authors(self,obj): # 上面自定义显示的方法#     retobj.authors.all()#     ssAuthorSerializer(ret,manyTrue)#     return ss.dataclass BookViewSet(APIView):def get(self,request,*args,**kwargs):book_listBook.objects.all()# 序列化方式1:# from django.forms.models import model_to_dict# import json# data[]# for obj in book_list:#     data.append(model_to_dict(obj))# print(data)# return HttpResponse(ok)# 序列化方式2:# dataserializers.serialize(json,book_list)# return HttpResponse(data)# 序列化方式3:bsBookSerializers(book_list,manyTrue)     #manyTrue代表有多条数据如果只有一条数据manyFalsereturn Response(bs.data)# 序列化方式4: # retmodels.Book.objects.all().values(nid,title)# ddlist(ret)# return HttpResponse(json.dumps(dd)) 注意 
source 如果是字段会显示字段如果是方法会执行方法不用加括号authorsserializers.CharField(sourceauthors.all) 
如在模型中定义一个方法直接可以在在source指定执行 class UserInfo(models.Model):user_type_choices  ((1,普通用户),(2,VIP),(3,SVIP),)user_type  models.IntegerField(choicesuser_type_choices)username  models.CharField(max_length32,uniqueTrue)password  models.CharField(max_length64)#视图
retmodels.UserInfo.objects.filter(pk1).first()
aaret.get_user_type_display()#serializer
xxserializers.CharField(sourceget_user_type_display)