01_Tutorial 1: Serialization 序列化
1、序列化
1、官方教程
https://q1mi.github.io/Django-REST-framework-documentation/tutorial/1-serialization_zh/
https://www.django-rest-framework.org/tutorial/1-serialization/
2、序列化方式1:serializers.Serializer
# 序列化方式1:serializers.Serializer
# 序列化方式1:serializers.Serializer class SnippetSerializer1(serializers.Serializer): """序列化,正反""" """ 序列化字段 GET请求 """ id = serializers.IntegerField(read_only=True) title = serializers.CharField(required=False, allow_blank=True, max_length=100) code = serializers.CharField(style={'base_template': 'textarea.html'}) # 多文本框的类型,比如XML,HTML,SHELL, python # 在某些情况下如何显示,比如渲染HTML的时候 # {'base_template': 'textarea.html'}标志等同于在Django Form类中使用widget=widgets.Textarea linenos = serializers.BooleanField(required=True) language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python') style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly') """ 反序列化字段 POST,PUT请求 """ def create(self, validated_data): """ 根据提供的验证过的数据,创建并返回一个新的snippet实例 """ return Snippet.objects.create(**validated_data) # 保存到数据库 def update(self, instance, validated_data): """ 根据提供的验证过的数据更新和返回一个已经存在的`Snippet`实例。 """ instance.title = validated_data.get('title', instance.title) # 如果post该字段则取该字段,否则直接从instance中取 instance.code = validated_data.get('code', instance.code) instance.linenos = validated_data.get('linenos', instance.linenos) instance.language = validated_data.get('language', instance.language) instance.style = validated_data.get('style', instance.style) instance.save() # 保存到db return instance
3、view视图
from django.test import TestCase # Create your tests here. from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser # ## 序列化 GET方法 def test1(): snippet = Snippet(code='foo = "bar"\n') snippet.save() snippet = Snippet(code='print "hello world"\n') # 获取字段,其他的都default snippet.save() # 保存到db serializer = SnippetSerializer(snippet) # 序列化为一个class对象 serializer.data # {'id': 2, 'title': '', 'code': 'print "hello world"\n', 'linenos': False, 'language': 'python', 'style': 'friendly'} type(serializer.data) # 现在是什么类型呢? ReturnDict # <class 'rest_framework.utils.serializer_helpers.ReturnDict'> content = JSONRenderer().render(serializer.data) # 转化为json, Python原生数据类型 # content # b'{"id":2,"title":"","code":"print \\"hello world\\"\\n","linenos":false,"language":"python","style":"friendly"}' type(content) # <class 'bytes'> # ## 反序列化 POST PUT def test2(content): from django.utils.six import BytesIO # IO,内存的数据 stream = BytesIO(content) # 获取内存中的数据 # <_io.BytesIO object at 0x00000264CC1FE780> data = JSONParser().parse(stream) # 解析为data,什么类型? 一个流(stream)解析为Python原生数据类型 type(data) # <class 'dict'> serializer = SnippetSerializer(data=data) # 序列化 serializer.is_valid() # 校验 # True serializer.validated_data # 校验通过的数据 # OrderedDict([('title', ''), ('code', 'print "hello world"'),('linenos', False), ('language', 'python'), ('style', 'friendly')]) type(serializer.validated_data) # <class 'collections.OrderedDict'> serializer.save() # 保存到db,什么类型? 将Python原生数据类型恢复成正常的对象实例 # <Snippet: Snippet object (3)>
总结
# ## 总结 ''' POST方法create 反序列化 Python原生数据类型 ---> 模型实例 1、json类型的数据,每个字段必须存在 b'{"id":2,"title":"","code":"print \\"hello world\\"\\n","linenos":false,"language":"python","style":"friendly"}' 2、解析成为dict字典,<class 'dict'> Python原生数据类型 data = JSONParser().parse(stream) 3、序列化,<class 'snippets.serializers.SnippetSerializer'> serializer = SnippetSerializer(data=data) 4、是否校验通过 serializer.is_valid() 5、校验后的数据, <class 'collections.OrderedDict'> serializer.validated_data 6、保存到DB,<Snippet: Snippet object (3)> 正常的对象实例 serializer.save() ''' ''' GET list方法总结 序列化 模型实例 ---> Python原生数据类型 1、接收每个字段,snippet = Snippet(code='foo = "bar"\n') code='foo = "bar"\n', title='', style='friendly',language='python', linenos=False 2、保存到DB <class 'snippets.models.Snippet'> snippet.save() 3、序列化,对象 模型实例 serializer = SnippetSerializer(snippet) 4、序列化的数据 # <class 'rest_framework.utils.serializer_helpers.ReturnDict'> serializer.data 5、转换为json数据 <class 'bytes'> Python原生数据类型 content = JSONRenderer().render(serializer.data) '''
4、序列化方式2:推荐,serializers.ModelSerializers
# 序列化方式2:serializers.ModelSerializers (推荐)
"""
1、快捷方式
2、自动,确定一组字段
3、默认实现简单的create与update方法
# 序列化方式2:serializers.ModelSerializers (推荐) """ 1、快捷方式 2、自动,确定一组字段 3、默认实现简单的create与update方法 """ class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ['id', 'title', 'code', 'linenos', 'language', 'style']
查看所有字段
# 通过打印,序列化器类实例的结构(representation),查看它的所有字段。 from snippets.serializers import SnippetSerializer serializer = SnippetSerializer() print(serializer) print(repr(serializer)) # repr 规范string形式 # SnippetSerializer(): # id = IntegerField(label='ID', read_only=True) # title = CharField(allow_blank=True, max_length=100, required=False) # code = CharField(style={'base_template': 'textarea.html'}) # linenos = BooleanField(required=False) # language = ChoiceField(choices=[('Clipper', 'FoxPro'), ('Cucumber', 'Gherkin'), ('RobotFramework', 'RobotFramework'), ('abap', 'ABAP'), ('ada', 'Ada')... # style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...
5、视图
from django.shortcuts import render # Create your views here. from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.renderers import JSONRenderer # 渲染器 from rest_framework.parsers import JSONParser # 解析器 from snippets.models import Snippet from snippets.serializers import SnippetSerializer class JSONResponse(HttpResponse): """ 一个把content数据,渲染为json数据的HTTPResponse An HttpResponse that renders its content into JSON. """ def __init__(self, data, **kwargs): content = JSONRenderer().render(data) kwargs['content_type'] = 'applications/json' super(JSONResponse, self).__init__(content, **kwargs) # def __init__(self, content_type=None, status=None, reason=None, charset=None): # 列出所有现有的snippet或创建一个新的snippet /snippet @csrf_exempt # 从不具有CSRF令牌的客户端对此视图进行POST def snippet_list(request): """ 列出所有的code snippet,或创建1个新的snippet """ if request.method == 'GET': snippet = Snippet.objects.all() # queryset对象实例 serializer = SnippetSerializer(snippet, many=True) # serializer模型实例 return JSONResponse(serializer.data) # 序列化的数据 ReturnDict ---> json elif request.method == 'POST': data = JSONParser().parse(request) # python原生数据 ---> json serializer = SnippetSerializer(data=data) # serializer模型实例 if serializer.is_valid(): # data验证 serializer.save() # 保存到db, 正常的对象实例 return JSONResponse(serializer.data, status=201) # 验证通过的data,ReturnDict ---> json return JSONResponse(serializer.errors, status=400) # 未验证的通过的data, # 一个与单个snippet对象相应的视图 snippet/1 @csrf_exempt def snippet_detail(request, pk): """ 获取,更新,删除1个code snippet """ try: snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return HttpResponse(status=404) if request.method == 'GET': serializer = SnippetSerializer(snippet) return JSONResponse(serializer.data) elif request.method == 'POST': data = JSONParser().parse(request) serializer = SnippetSerializer(snippet, data=data) if serializer.is_valid(): serializer.save() return JSONResponse(serializer.data) return JSONResponse(serializer.errors, status=400) elif request.method == 'DELETE': snippet.delete() return HttpResponse(status=404)
6、效果