前言:昨天学习了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之序列化的更多相关文章

  1. Django Rest framework 之 序列化

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  2. Django REST Framework的序列化器是什么?

    # 转载请留言联系 用Django开发RESTful风格的API存在着很多重复的步骤.详细可见:https://www.cnblogs.com/chichung/p/9933861.html 过程往往 ...

  3. Django Rest Framework(2)-----序列化详解(serializers)

    REST framework中的序列化类与Django的Form和ModelForm类非常相似.我们提供了一个Serializer类,它提供了一种强大的通用方法来控制响应的输出,以及一个ModelSe ...

  4. Django restful Framework 之序列化与反序列化

    1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...

  5. Django rest framework之序列化小结

       最近在DRF的序列化上踩过了不少坑,特此结合官方文档记录下,方便日后查阅. [01]前言    serializers是什么?官网是这样的”Serializers allow complex d ...

  6. django rest framework serializers序列化

    serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用: - 将queryset与model实例等进行序列化,转化成json格式,返回给用户(a ...

  7. DRF Django REST framework 之 序列化(三)

    Django 原生 serializer (序列化) 导入模块 from django.core.serializers import serialize 获取queryset 对queryset进行 ...

  8. django-插件django REST framework,返回序列化的数据

    官网: http://www.django-rest-framework.org 1.安装 pip install djangorestframework 2.在setting.py中注册app 中添 ...

  9. django rest framework serializers

    django rest framework serializers序列化   serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用:- 将qu ...

  10. django rest framework 项目创建

    Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Rest Framework Django REST Framework可以在Django的基 ...

随机推荐

  1. 微信bug:建议了解,不要实验,不要手贱,不要。。。。

    今天下午在群里聊天的时候,群友反应发现微信的一个bug:使用微信给好友发送‘15...............’(数字15后面加15个句号)会导致微信运行缓慢,到最后的应用未响应,退出微信. 解决办法 ...

  2. 每周分享一 之 webSocket

    一:什么是webSocket ? webSocket是HTML5出的新协议,WebSocket协议支持,在受控环境中运行不受信任代码的客户端与选择了该代码通信的远程主机之间进行双向通信. 简单翻译一下 ...

  3. BP算法

    1986年Rumelhart和McCelland在<并行分布式处理>中提出了BP算法,即非线性连续变换函数的多层感知器网络误差反向传播算法. 该算法的思想是:学习过程分为信号的正向传播与误 ...

  4. Island Perimeter

    You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represen ...

  5. Intellij idea史上最简单的教程之Linux下安装与破解Intellij idea2017

    一.前言 这一节我们介绍在Linux下如何安装与破解Intellij idea2017.现在有很多公司开发环境都是Linux,所以掌握在Linux环境下使用Idea办公也是咱们必须得掌握的技能. 记住 ...

  6. 【NOIP】OpenJudge - 15-02:财务管理

    #include<stdio.h>//财务管理 int main() { ]={},sum=,ave=; ;i<=;i++) { scanf("%f",& ...

  7. 多个activity跳转保留内存使用intent传递数据问题_新手

    /////本来是做的activity跳转,普通那种,但是会在调回来会销毁原来的,重新调用onCreate方法, 后来参考[http://blog.csdn.net/qq_26918031/articl ...

  8. SQL监测语句

    SELECT top 20 qs.creation_time,last_execution_time,total_physical_reads,total_logical_reads,total_lo ...

  9. asp.net mvc 自动化测试工具

    好久不写文章了,一直忙在项目中. 前一阵发现公司一个项目,体积巨大.业务很复杂.基于历史原因,项目基于mvc 2迁移过来,视图大多还是aspx  作为视图承载. 控制器中的方法  更是一个比一个多. ...

  10. SQLite中的时间日期函数

    SQLite包含了如下时间/日期函数: datetime().......................产生日期和时间 date()...........................产生日期 t ...