Serializers 序列化组件
Django的序列化方法
<span style="color: #0000ff;">class
<span style="color: #000000;"> MyJson(json.JSONEncoder):<span style="color: #0000ff;">def<span style="color: #000000;"> default(self,field):
<span style="color: #0000ff;">if<span style="color: #000000;"> isinstance(field,datetime.datetime):
<span style="color: #0000ff;">return field.strftime(<span style="color: #800000;">'<span style="color: #800000;">%Y-%m-%d %H:%M:%s<span style="color: #800000;">'<span style="color: #000000;">)
<span style="color: #0000ff;">elif<span style="color: #000000;"> isinstance(field,datetime.date):
<span style="color: #0000ff;">return field.strftime(<span style="color: #800000;">'<span style="color: #800000;">%Y-%m-%d<span style="color: #800000;">'<span style="color: #000000;">)
<span style="color: #0000ff;">else<span style="color: #000000;">:
<span style="color: #0000ff;">return json.JSONEncoder.default(self,field)
<span style="color: #0000ff;">class<span style="color: #000000;"> BooksView(View):
<span style="color: #0000ff;">def<span style="color: #000000;"> get(self,request):
book_list =<span style="color: #000000;"> Book.objects.all()
ret = serializers.serialize(<span style="color: #800000;">"<span style="color: #800000;">json<span style="color: #800000;">"<span style="color: #000000;">,book_list)
<span style="color: #0000ff;">return HttpResponse(ret)
DRF序列化的方法
首先,我们要用DRF的序列化,就要遵循人家框架的一些标准,
-- Django我们CBV继承类是View,现在DRF我们要用APIView
-- Django中返回的时候我们用HTTPResponse,JsonResponse,render ,DRF我们用Response
为什么这么用~我们之后会详细讲~~我们继续来看序列化~~
序列化
<span style="color: #0000ff;">def<span style="color: #000000;"> get(self,request):
book_list =<span style="color: #000000;"> Book.objects.all()
ret = BookSerializer(book_list,many=<span style="color: #000000;">True)
<span style="color: #0000ff;">return Response(ret.data)
外键关系的序列化
id = serializers.IntegerField(read_only=<span style="color: #000000;">True)
title = serializers.CharField(max_length=32<span style="color: #000000;">) <span style="color: #0000ff;">class<span style="color: #000000;"> UserSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=<span style="color: #000000;">True)
name = serializers.CharField(max_length=32<span style="color: #000000;">)
age =<span style="color: #000000;"> serializers.IntegerField()
<span style="color: #0000ff;">class<span style="color: #000000;"> BookSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=<span style="color: #000000;">True)
title = serializers.CharField(max_length=32<span style="color: #000000;">)
CHOICES = ((1,source=<span style="color: #800000;">"<span style="color: #800000;">getchapterdisplay<span style="color: #800000;">",read_only=<span style="color: #000000;">True)
pub_time =<span style="color: #000000;"> serializers.DateField()
publisher </span>= PublisherSerializer(read_only=<span style="color: #000000;">True)
user </span>= UserSerializer(many=True,read_only=True)</pre>
反序列化
当前端给我们发post的请求的时候~前端给我们传过来的数据~我们要进行一些校验然后保存到数据库~
这些校验以及保存工作,DRF的Serializer也给我们提供了一些方法了~~
首先~我们要写反序列化用的一些字段~有些字段要跟序列化区分开~~
Serializer提供了.is_valid() 和.save()方法~~
publisher </span>= PublisherSerializer(read_only=<span style="color: #000000;">True)
user </span>= UserSerializer(many=True,read_only=<span style="color: #000000;">True)
users </span>= serializers.ListField(write_only=<span style="color: #000000;">True)
publisher_id </span>= serializers.IntegerField(write_only=<span style="color: #000000;">True)
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> create(self,validated_data):
book </span>= Book.objects.create(title=validated_data[<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span>],chapter=validated_data[<span style="color: #800000;">"</span><span style="color: #800000;">w_chapter</span><span style="color: #800000;">"</span>],pub_time=validated_data[<span style="color: #800000;">"</span><span style="color: #800000;">pub_time</span><span style="color: #800000;">"</span>],publisher_id=validated_data[<span style="color: #800000;">"</span><span style="color: #800000;">publisher_id</span><span style="color: #800000;">"</span><span style="color: #000000;">])
book.user.add(</span>*validated_data[<span style="color: #800000;">"</span><span style="color: #800000;">users</span><span style="color: #800000;">"</span><span style="color: #000000;">])
</span><span style="color: #0000ff;">return</span> book</pre>
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> post(self,request):
</span><span style="color: #008000;">#</span><span style="color: #008000;"> book_obj = request.data</span>
<span style="color: #0000ff;">print</span><span style="color: #000000;">(request.data)
serializer </span>= BookSerializer(data=<span style="color: #000000;">request.data)
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> serializer.is_valid():
</span><span style="color: #0000ff;">print</span>(12341253<span style="color: #000000;">)
serializer.save()
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(serializer.validated_data)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
</span><span style="color: #0000ff;">return</span> Response(serializer.errors)</pre>
但前端给我们发送patch请求的时候,前端传给我们用户需要更新的数据,我们要对数据进行部分验证.
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> update(self,instance,validated_data):
instance.title </span>= validated_data.get(<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span><span style="color: #000000;">,instance.title)
instance.chapter </span>= validated_data.get(<span style="color: #800000;">"</span><span style="color: #800000;">w_chapter</span><span style="color: #800000;">"</span><span style="color: #000000;">,instance.chapter)
instance.pub_time </span>= validated_data.get(<span style="color: #800000;">"</span><span style="color: #800000;">pub_time</span><span style="color: #800000;">"</span><span style="color: #000000;">,instance.pub_time)
instance.publisher_id </span>= validated_data.get(<span style="color: #800000;">"</span><span style="color: #800000;">publisher_id</span><span style="color: #800000;">"</span><span style="color: #000000;">,instance.publisher_id)
</span><span style="color: #0000ff;">if</span> validated_data.get(<span style="color: #800000;">"</span><span style="color: #800000;">users</span><span style="color: #800000;">"</span><span style="color: #000000;">):
instance.user.set(validated_data.get(</span><span style="color: #800000;">"</span><span style="color: #800000;">users</span><span style="color: #800000;">"</span><span style="color: #000000;">))
instance.save()
</span><span style="color: #0000ff;">return</span> instance</pre>
验证
如果我们需要对一些字段进行自定义的验证~DRF也给我们提供了钩子方法.
<span style="color: #008000;">#</span><span style="color: #008000;"> 对多个字段进行验证 要求上架日期不能早于出版日期 上架日期要大</span>
<span style="color: #0000ff;">def</span><span style="color: #000000;"> validate(self,attrs):
</span><span style="color: #0000ff;">if</span> attrs[<span style="color: #800000;">"</span><span style="color: #800000;">pub_time</span><span style="color: #800000;">"</span>] > attrs[<span style="color: #800000;">"</span><span style="color: #800000;">date_added</span><span style="color: #800000;">"</span><span style="color: #000000;">]:
</span><span style="color: #0000ff;">raise</span> serializers.ValidationError(<span style="color: #800000;">"</span><span style="color: #800000;">上架日期不能早于出版日期</span><span style="color: #800000;">"</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">return</span> attrs</pre>
id = serializers.IntegerField(read_only=<span style="color: #000000;">True)
title = serializers.CharField(max_length=32,validators=<span style="color: #000000;">[my_validate])
<span style="color: #008000;">#<span style="color: #008000;"> 。。。。。。
ModelSerializer
现在我们已经清楚了Serializer的用法,会发现我们所有的序列化跟我们的模型都紧密相关~
那么,DRF也给我们提供了跟模型紧密相关的序列化器~~ModelSerializer~~
-- 它简单的默认实现了.update()以及.create()方法
定义一个ModelSerializer序列化器
外键关系的序列化
注意:当序列化类MATE中定义了depth时,这个序列化类中引用字段(外键)则自动变为只读
自定义字段
我们可以声明一些字段来覆盖默认字段,来进行自定制~
比如我们的选择字段,默认显示的是选择的key,我们要给用户展示的是value。
</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> <a href="/tag/Meta/" target="_blank" class="keywords">Meta</a>:
model </span>=<span style="color: #000000;"> Book
fields </span>= <span style="color: #800000;">"</span><span style="color: #800000;">__all__</span><span style="color: #800000;">"</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> fields = ["id","pub_time"]</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> exclude = ["user"]</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 分别是所有字段 包含某些字段 排除某些字段</span>
depth = 1</pre>
Meta中其它关键字参数
</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> <a href="/tag/Meta/" target="_blank" class="keywords">Meta</a>:
model </span>=<span style="color: #000000;"> Book
fields </span>= <span style="color: #800000;">"</span><span style="color: #800000;">__all__</span><span style="color: #800000;">"</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> fields = ["id","pub_time"]</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> exclude = ["user"]</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 分别是所有字段 包含某些字段 排除某些字段</span>
depth = 1<span style="color: #000000;">
read_only_fields </span>= [<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span><span style="color: #000000;">]
extra_<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a> </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span>: {<span style="color: #800000;">"</span><span style="color: #800000;">validators</span><span style="color: #800000;">"</span>: [my_validate,]}}</pre>
post以及patch请求
由于depth会让我们外键变成只读,所以我们再定义一个序列化的类,其实只要去掉depth就可以了
SerializerMethodField
外键关联的对象有很多字段我们是用不到的~都传给前端会有数据冗余~就需要我们自己去定制序列化外键对象的哪些字段~~
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_user(self,obj):
</span><span style="color: #008000;">#</span><span style="color: #008000;"> obj是当前序列化的book对象</span>
users_query_set =<span style="color: #000000;"> obj.user.all()
</span><span style="color: #0000ff;">return</span> [{<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>: user_obj.pk,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>: user_obj.name} <span style="color: #0000ff;">for</span> user_obj <span style="color: #0000ff;">in</span><span style="color: #000000;"> users_query_set]
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_publisher(self,obj):
publisher_obj </span>=<span style="color: #000000;"> obj.publisher
</span><span style="color: #0000ff;">return</span> {<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>: publisher_obj.pk,<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span><span style="color: #000000;">: publisher_obj.title}
</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> <a href="/tag/Meta/" target="_blank" class="keywords">Meta</a>:
model </span>=<span style="color: #000000;"> Book
fields </span>= <span style="color: #800000;">"</span><span style="color: #800000;">__all__</span><span style="color: #800000;">"</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> fields = ["id",]}}</pre>
用ModelSerializer改进上面Serializer的完整版
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_users(self,<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>: user_obj.name} <span style="color: #0000ff;">for</span> user_obj <span style="color: #0000ff;">in</span><span style="color: #000000;"> users_query_set]
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_publishers(self,<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span><span style="color: #000000;">: publisher_obj.title}
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_<a href="/tag/dis/" target="_blank" class="keywords">dis</a>_chapter(self,obj):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> obj.get_chapter_<a href="/tag/dis/" target="_blank" class="keywords">dis</a>play()
</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> <a href="/tag/Meta/" target="_blank" class="keywords">Meta</a>:
model </span>=<span style="color: #000000;"> Book
</span><span style="color: #008000;">#</span><span style="color: #008000;"> fields = "__all__"</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 字段是有序的</span>
fields = [<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;"><a href="/tag/dis/" target="_blank" class="keywords">dis</a>_chapter</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">publishers</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">users</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">publisher</span><span style="color: #800000;">"</span><span style="color: #000000;">]
</span><span style="color: #008000;">#</span><span style="color: #008000;"> exclude = ["user"]</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 分别是所有字段 包含某些字段 排除某些字段</span>
read_only_fields = [<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">publishers</span><span style="color: #800000;">"</span><span style="color: #000000;">]
extra_<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a> </span>= {<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span>: {<span style="color: #800000;">"</span><span style="color: #800000;">validators</span><span style="color: #800000;">"</span>: [my_validate,]},<span style="color: #800000;">"</span><span style="color: #800000;">user</span><span style="color: #800000;">"</span>: {<span style="color: #800000;">"</span><span style="color: #800000;">write_only</span><span style="color: #800000;">"</span>: True},<span style="color: #800000;">"</span><span style="color: #800000;">publisher</span><span style="color: #800000;">"</span>: {<span style="color: #800000;">"</span><span style="color: #800000;">write_only</span><span style="color: #800000;">"</span><span style="color: #000000;">: True},</span><span style="color: #800000;">"</span><span style="color: #800000;">chapter</span><span style="color: #800000;">"</span>: {<span style="color: #800000;">"</span><span style="color: #800000;">write_only</span><span style="color: #800000;">"</span>: True}}</pre>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。