django-rest-framework学习之路-2-序列化
作者:互联网
django-rest-framework学习之路-2-序列化
1、引入概念
我们想把一个对象封装后提供出一个接口给其他人用,根据约定好的格式进行数据传递,比如使用Json。
例如
import pprint
class Student:
def __init__(self, stu_id, name, age):
self.stu_id = stu_id
self.name = name
self.age = age
def to_json(self):
info = dict(stu_id=self.stu_id, name=self.name, age=self.age)
pprint.pprint(info)
return info
if __name__ == '__main__':
student = Student(10086, '墨玉麒麟', 18)
student_info = student.to_json()
print(f"学生的信息是:{student_info}")
同理,我们也要约定一种格式,在django之间数把数据传递给其他人用,因此,我们需要序列化代码片段,上面的做法就是使用json序列化Student对象,来进行数据之间的传递。
在django-rest-framework中,我们使用serializers库来进行数据的序列化,可以理解为这是django-rest-framework的约定。
2、创建一个序列化类
在snippets的目录下创建一个名为serializers.py文件,添加以下内容
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
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'})
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
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)
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()
return instance
说明
- 序列化器类的第一部分定义了序列化/反序列化的字段。create()和update()方法定义了在调用serializer.save()时如何创建和修改完整的实例。
- 序列化器类与Django Form类非常相似,并在各种字段中包含类似的验证标志,例如required,max_length和default。
- 字段标志还可以控制serializer在某些情况下如何显示,比如渲染HTML的时候。上面的{'base_template': 'textarea.html'}标志等同于在Django Form类中使用widget=widgets.Textarea。这对于控制如何显示可浏览器浏览的API特别有用,我们将在本教程的后面看到。
- 我们实际上也可以通过使用ModelSerializer类来节省时间,就像我们后面会用到的那样。但是现在我们还继续使用我们明确定义的serializer。
3、熟悉序列化类
我们进入django的shell中,来熟悉一下我们刚才新建的序列化类SnippetSerializer
使用刚才的cmd窗口(当然也可以新开一个窗口,只要保证目录在我们的项目目录下即可)
运行命令,进入shell交互
python manage.py shell
先来创建两个Snippet对象,然后保存到数据库
from snippets.models import Snippet
snippet = Snippet(code='foo = "bar"\n')
snippet.save()
snippet = Snippet(code='print "hello, world"\n')
snippet.save()
这样数据库就保存了两个Snippet对象,也就是两条数据库记录
数据库文件就是项目目录下的db.sqlite3,使用任意一个sqlite可视化工具都可以查看它,例如我用的是SQLiteStudio
接下来就是序列化刚才创建的Snippet对象
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer(snippet)
serializer.data
print(type(serializer.data))
把序列化后的数据转成bytes流
from rest_framework.renderers import JSONRenderer
content = JSONRenderer().render(serializer.data)
print(content)
print(type(content))
当然也可以把流形式反序列化回来
from io import BytesIO
from rest_framework.parsers import JSONParser
stream = BytesIO(content)
data = JSONParser().parse(stream)
serializer = SnippetSerializer(data=data)
serializer.is_valid()
serializer.data
我们也可以序列化所有的Snippet对象,而不是只序列化一个,通过参数many=True即可
serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
4、使用模型序列化
之所以SnippetSerializer类能序列化Snippet对象,是因为我们定义的SnippetSerializer类和Snippet很相似,可以说是把Snippet对象的属性搬过来了一份,我们想要序列化哪一个属性,我们就搬哪一个属性过来,有点映射的味道了吧。
那么我们是否可以直接使用Snippet模型对象类构建SnippetSerializer序列化类呢,那当然是必然的,我们可以这样子构建
4.1、修改snippets/serializers.py文件内容为如下内容
from rest_framework import serializers
from snippets.models import Snippet
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
4.2、可以通过repr来查看序列化类序列化了哪些字段
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))
还是在cmd中查看一下
别慌,后面这些乱七八糟的是language的选项而已,同时也能看到style的选项
5、使用序列化类编写视图函数
接下来,我们通过序列化类进行视图的编写
在snippets/views.py文件中添加如下代码
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data) # 把序列化对象转为bytes流
print(type(content))
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
@csrf_exempt
def snippet_list(request):
"""
列出所有的code snippet,或创建一个新的snippet。
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JSONResponse(serializer.data)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data, status=201)
return JSONResponse(serializer.errors, status=400)
@csrf_exempt
def snippet_detail(request, pk):
"""
获取,更新或删除一个 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 == 'PUT':
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=204)
-
snippet_list视图支持列出所有现有的snippet或创建一个新的snippet。
-
snippet_detail视图,并且用于获取,更新和删除这个snippet。
我们需要添加对应的路由
创建一个snippets/urls.py文件,添加如下代码
from django.urls import re_path
from snippets import views
urlpatterns = [
re_path(r'^snippets/$', views.snippet_list),
re_path(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]
把snippets app的路由注册到tutorial/urls.py中
在tutorial/urls.py添加如下代码
from django.urls import include
path('snippets/', include('snippets.urls')),
6、启动服务,查看序列化效果
退出刚才的cmd或者直接关闭
启动服务
python manage.py runserver
打开浏览器,查看效果
地址:http://127.0.0.1:8000/snippets/snippets/
地址:http://127.0.0.1:8000/snippets/snippets/1/
当然,这两个都是get的用法
使用Apipost模拟调试
- 获取所有的Snippet对象
curl --location --request GET --X GET 'http://127.0.0.1:8000/snippets/snippets' \
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/'
- 创建一个Snippet对象
curl --location --request POST --X POST 'http://127.0.0.1:8000/snippets/snippets/' \
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/' \
--header 'Content-Type: application/json' \
--data ' {
"title": "测试1",
"code": "foo = \"bar1\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
}'
数据库
- 获取一个Snippet对象
curl --location --request GET --X GET 'http://127.0.0.1:8000/snippets/snippets/3' \
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/'
- 修改一个Snippet对象
curl --location --request PUT --X PUT 'http://127.0.0.1:8000/snippets/snippets/3/' \
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/' \
--header 'Content-Type: application/json' \
--data '{
"title": "测试1更名",
"code": "foo = \"bar1-更名\"",
"linenos": false,
"language": "python",
"style": "friendly"
}'
数据库
- 删除一个Snippet对象
curl --location --request DELETE --X DELETE 'http://127.0.0.1:8000/snippets/snippets/3/' \
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/'
数据库
学习链接:https://www.w3cschool.cn/lxraw/lxraw-8kq335ob.html
标签:--,rest,django,Snippet,snippets,序列化,data,serializer 来源: https://www.cnblogs.com/rainbow-tan/p/16270028.html