django-rest-framework之序列化
前言:昨天学习了rest-framework序列化方面的知识,故写了博客记录一下。官网:http://www.django-rest-framework.org/tutorial/1-serialization/#working-with-serializers。
前后端分离:前台的开发和后台的开发分离开。这个方案的实现就是要借助API,API简单说就是开发人员提供编程接口被其他人调用,他们调用之后会返回数据供其使用。API的类型有多种,但是现在比较主流且实用的就是RESTful API。
一、开始
Okay, we're ready to get coding. To get started, let's create a new project to work with.首先创建一个Django项目。
cd ~
django-admin.py startproject tutorial
cd tutorial
Once that's done we can create an app that we'll use to create a simple Web API.接着创建一个APP
python manage.py startapp snippets
We'll need to add our new snippets
app and the rest_framework
app to INSTALLED_APPS
. Let's edit the tutorial/settings.py
file:修改全局配置文件。
INSTALLED_APPS = (
...
'rest_framework',
'snippets.apps.SnippetsConfig',
)
Please note that if you're using Django <1.9, you need to replace snippets.apps.SnippetsConfig
with snippets
.
如果你使用的Django <1.9,则需要更换snippets.apps.SnippetsConfig为
snippets
。
二、创建模型类
For the purposes of this tutorial we're going to start by creating a simple Snippet
model that is used to store code snippets(片段). Go ahead and edit the snippets/models.py
file.
我们将首先创建一个Snippet
用于存储代码片段的简单模型,编辑snippets/models.py
文件。
from django.db import models # Create your models here. # pygments可以实现代码高亮 官网:http://pygments.org/
from pygments.lexers import get_all_lexers # lexers:词法分析器
from pygments.styles import get_all_styles LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles()) class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True) # 自动添加创建时间
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100) class Meta:
ordering = ('created',) # 根据创建时间来排序
初始化并且同步到数据库:
python manage.py makemigrations snippets
python manage.py migrate
三、创建序列化类
The first thing we need to get started on our Web API is to provide a way of serializing(序列化) and deserializing(反序列化) the snippet instances into representations such as json
. We can do this by declaring(声明) serializers that work very similar to Django's forms.
首先我要问你了,通常情况下,前端从调用后台API,API肯定需要返回数据给前端,那返回的数据是什么类型呢?
目前主流用的比较多的是JSON,可能有少部分还在用XML。
那我们在学习django-rest-framework时,有没有提供什么方法能够将数据实例信息自动转换为JSON?而且也可以将前端传给后台的JSON数据转换为python的数据类型(dict/list/set...)。当然有,序列化器(serializers)可以实现。首先你得声明(引入)序列化器,请看下面这个例子:
# 用Web API的第一件事是提供一种将代码片段实例序列化和反序列化为表示形式的方法json。
# 我们可以通过声明与Django表单非常相似的序列化器来做到这一点。在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)
# 利用字段标志控制序列化器渲染到HTML页面时的的显示模板
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):
"""
The create() and update() methods define how fully fledged instances are created
or modified when calling serializer.save()
Create and return a new `Snippet` instance, given the validated data.
给定经过验证的数据,创建并返回一个新的 Snippet 实例
"""
return Snippet.objects.create(**validated_data) def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the 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()
方法分别定义实例如何创建和更新。
关于下面这行代码:
code = serializers.CharField(style={'base_template': 'textarea.html'})
暂时需要知道的就是它的功能是控制序列化器渲染到HTML页面时的的显示模板,至于为什么要这样做,是因为这对于控制如何显示可浏览的API特别有用,这将在后面的文章中看到。
实际上也可以通过使用ModelSerializer
来节省自己的时间,我们稍后会看到,接下来看看序列化器的具体作用。
四、使用序列化器
在我们进一步了解之前,我们将熟悉使用我们新的Serializer类。我们进入Django shell:
python manage.py shell
接下来的操作就和学习Django的ORM时那样,创建并保存Snippet模型实例:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser snippet = Snippet(code='foo = "bar"\n')
snippet.save() snippet = Snippet(code='print "hello, world"\n')
snippet.save()
这个时候查看数据库就会发现相关的表中已经多了两行数据,就是我们刚才创建的数据:
我们现在有几个片段实例可以玩。我们来看看序列化这些实例之一
serializer = SnippetSerializer(snippet)
serializer.data
# {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
At this point we've translated the model instance into Python native datatypes.
从上面的代码,可以看到,我们已经将model的实例信息转换为python原生的数据类型,即字典。
To finalize the serialization process we render the data into json
.
为了完成序列化过程,我们将数据转换成json
。
content = JSONRenderer().render(serializer.data)
content
# '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
这里已经出现了json格式,也就是说这个json格式的数据就是要展示在某个URL上,大概可以感觉到,等下我们在访问某个URL时,会返回上面这堆数据供你使用,这其实就完成了一个序列化的过程,也可以看出客户端的功能雏形。
序列化是为了返回json格式的数据给客户端查看和使用数据,那么当客户端需要修改、增加或者删除数据时,就要把过程反过来了,也就是反序列化,把客户端提交的json格式的数据反序列化。
反序列化是类似的。首先我们将一个流解析为Python本机数据类型...
from django.utils.six import BytesIO stream = BytesIO(content)
data = JSONParser().parse(stream)
...then we restore those native datatypes into a fully populated object instance.
先检查数据是否有误,再保存数据:
serializer = SnippetSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
# <Snippet: Snippet object>
这个时候查看数据库又多了一条数据:
We can also serialize querysets instead of model instances. To do so we simply add a many=True
flag to the serializer arguments.
我们也可以序列化查询集而不是模型实例。为此,我们只需要为serializer参数添加一个标志many=True
serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]
五、使用 ModelSerializers
在上面的SnippetSerializer类中,我们继承的是serializers.Serializer类,可以看到SnippetSerializer类中有很多代码其实是和models.py中的Snippet模型类似一样的,所以这里我们可以改进一下。就像在Django中提供了Form类和ModelForm类一样,django-rest-framework为我们提供了Serializer类和ModelSerializer类。利用它可以让我们的代码简洁很多,修改serializers.py:
# Our SnippetSerializer class is replicating a lot of information that's also contained in the Snippet model.
# It would be nice if we could keep our code a bit more concise.
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
One nice property that serializers have is that you can inspect(检查/查看) all the fields in a serializer instance, by printing its representation. Open the Django shell with python manage.py shell
, then try the following:
序列化器具有的一个不错的属性是可以通过打印其表示来检查序列化器实例中的所有字段。打开Django shell python manage.py shell
,然后尝试以下操作:
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))
# 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')...
记住,ModelSerializer类不会做任何特别神奇的事情,它们只是创建序列化器类的快捷方式:
- 一组自动确定的字段。
- 简单的默认实现create()和update()方法。
六、编写常规的Django视图
接下来要做的就是使用我们的新的Serializer类编写一些API视图。编辑snippets/views.py:
from django.shortcuts import render # Create your views here.
from django.http import HttpResponse, JsonResponse
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 @csrf_exempt
def snippet_list(request):
"""
because we want to be able to POST to this view from clients
that won't have a CSRF token we need to mark the view as csrf_exempt
List all code snippets, or create a new snippet.
"""
if request.method == "GET":
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JsonResponse(serializer.data, safe=False) 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):
"""
Retrieve, update or delete a 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)
上面的代码都比较好理解,定义了不同http动作时后台不同的操作,在这里也体现了restful API的理念。
because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as csrf_exempt
.
因为我们希望能够从不具有CSRF令牌的客户端对此视图进行POST,因此我们需要给视图加个一个装饰器csrf_exempt
为了让视图函数被调用,那当然需要设计一下url了,这里的处理和平时Django开发时是一样的。首先创建snippets/urls.py
from django.conf.urls import url
from snippets import views urlpatterns = [
url(r'^snippets/$', views.snippet_list),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]
We also need to wire up the root urlconf, in the tutorial/urls.py
file, to include our snippet app's URLs.
from django.conf.urls import url, include urlpatterns = [
url(r'^', include('snippets.urls')),
]
七、对API进行测试
完成了上面那些工作后,就可以开始测试了,退出shell模式并启动服务器,根据我们刚才设计的url发送请求,需要先安装httpie模块:
pip install httpie
然后在命令行窗口访问,效果如下:
也可以访问指定id的数据:
当然了,也可以直接在浏览器查看,直接输入那个URL就可以了:
django-rest-framework之序列化的更多相关文章
- Django Rest framework 之 序列化
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django REST Framework的序列化器是什么?
# 转载请留言联系 用Django开发RESTful风格的API存在着很多重复的步骤.详细可见:https://www.cnblogs.com/chichung/p/9933861.html 过程往往 ...
- Django Rest Framework(2)-----序列化详解(serializers)
REST framework中的序列化类与Django的Form和ModelForm类非常相似.我们提供了一个Serializer类,它提供了一种强大的通用方法来控制响应的输出,以及一个ModelSe ...
- Django restful Framework 之序列化与反序列化
1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...
- Django rest framework之序列化小结
最近在DRF的序列化上踩过了不少坑,特此结合官方文档记录下,方便日后查阅. [01]前言 serializers是什么?官网是这样的”Serializers allow complex d ...
- django rest framework serializers序列化
serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用: - 将queryset与model实例等进行序列化,转化成json格式,返回给用户(a ...
- DRF Django REST framework 之 序列化(三)
Django 原生 serializer (序列化) 导入模块 from django.core.serializers import serialize 获取queryset 对queryset进行 ...
- django-插件django REST framework,返回序列化的数据
官网: http://www.django-rest-framework.org 1.安装 pip install djangorestframework 2.在setting.py中注册app 中添 ...
- django rest framework serializers
django rest framework serializers序列化 serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用:- 将qu ...
- django rest framework 项目创建
Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Rest Framework Django REST Framework可以在Django的基 ...
随机推荐
- Bootstrap框架的了解和使用之栅格系统
前 言 Bootstrap Bootstrap 包含了一个响应式的.移动设备优先的.不固定的网格系统,可以随着设备或视口大小的增加而适当地扩展到 12 列.它包含了用于简单的布局选项的预定 ...
- js中如何在一个函数里面执行另一个函数
1.js中如何在函数a里面执行函数b function a(参数c){ b(); } function b(参数c){ } 方法2: <script type="text/javasc ...
- ActiveMQ 入门helloworld
1.下载安装ActiveMQ 官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Unix 等几个版本 ...
- 编译httpd细节
html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...
- crontab的两大坑:百分号和环境变量
今天想给服务器加个自动备份mysql数据库的功能(别怪我这么久才加,阿里云每天全盘备份的,不怕丢数据库),本以为只要5分钟就能搞定的,结果入了两个大坑. 我的crontab是这样写的: * * * m ...
- UWP 自定义状态栏
在UWP开发中,我们可以改变状态栏样式,让你的应用更加好看. 先来一简单的应用: 为了做例子,所以我做的很简单,在MainPage的Grid里,插了一个Image <Grid Backgroun ...
- centos7下安装tesseract-ocr进行验证码识别
摘要: centos7安装依赖库 tesseract配置 代码例子 centos7安装依赖库 安装centos系统依赖 yum install -y automake autoconf libtool ...
- ZOJ 1489 HDU1395 2^x mod n = 1 数学
2^x mod n = 1 Time Limit: 2 Seconds Memory Limit:65536 KB Give a number n, find the minimum x t ...
- Python内置类型(2)——布尔运算
python中bool运算符按优先级顺序分别有or.and.not, 其中or.and为短路运算符 not先对表达式进行真值测试后再取反 not运算符值只有1个表达式,not先对表达式进行真值测试后再 ...
- JavaWeb学习笔记——jquery中的dom操作
jquery中的dom操作 废话不说:直接上例子: 1.添加节点-html页面 Append:向每个匹配的元素内部追加内容. <body> <ul id="city& ...