介绍

本教程将会通过创建一个简单的粘贴代码项目,突出显示WebAPI,过程中,会介绍组成REST框架的各种组件,让你全面了解如何配合使用。

环境设置

建议使用virtualenv建立新的虚拟环境,确保本项目所依赖的任何包和其他环境保持隔离

virtualenv env
source env/bin/activate

现在在新的虚拟环境中安装必须的包

pip install django
pip install djangorestframework
pip install pygments #代码高亮使用

创建项目

我们将创建名为tutorial的项目,在项目中创建名为snippets的app

django-admin.py startproject tutorial
cd tutorial
python manage.py startapp snippets

最后我们需要在settings.pyINSTALLED_APPS配置里注册我们的snippetsapp和rest_frameworkapp

INSTALLED_APPS = [
...
'rest_framework',
'snippets.apps.SnippetsConfig',
]

注意:如果使用的django版本低于1.9,直接使用snippets 来代替snippets.apps.SnippetsConfig即可

创建model

下面创建snippets所使用的数据库表用来存储代码

from django.db import models

from pygments.lexers import get_all_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

创建序列化的类

首先我们需要为api提供序列化和反序列化的方法,将snippet实例转为json等方式呈现数据,我们可以使用Serializer达到这一目的, Serializer和django forms十分相似. 我们在snippetapp下新建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

serializer的首先定义了序列化和反序列化的字段,其次create()update()方法定义了当调用serializer.save()时如何对实例进行创建或修改

serializer和django的form非常类似,而且包括一些类似的验证字段的方法,如required,max_lengthanddefault.

使用Serializers

我们使用django的shell 环境来简单的测试Serializers

创建两个snippet实例

python3 manage.py shell

>>> 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()
>>> snippet2 = Snippet(code='print "hello, world"\n')
>>> snippet2.save()

序列化其中一个实例

>>> serializer = SnippetSerializer(snippet2)
>>> serializer.data
{'linenos': False, 'id': 2, 'code': 'print "hello, world"\n', 'language': 'python', 'style': 'friendly', 'title': ''}

我们已经将snippet2序列化为一个python的基本数据类型,现在我们生成json数据

>>> content = JSONRenderer().render(serializer.data)
>>> content
b'{"id":2,"title":"","code":"print \\"hello, world\\"\\n","linenos":false,"language":"python","style":"friendly"}'

反序列化更简单,首先将stream转为python基本类型

>>> from django.utils.six import BytesIO
>>> stream = BytesIO(content)
>>> data = JSONParser().parse(stream)
>>> data
{'linenos': False, 'id': 2, 'code': 'print "hello, world"\n', 'language': 'python', 'style': 'friendly', 'title': ''}

然后,我们将其转换为snippet实例

>>> serializer = SnippetSerializer(data=data)
>>> serializer.is_valid()
True
>>> serializer.validated_data
OrderedDict([('title', ''), ('code', 'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
>>> serializer.save()
<Snippet: Snippet object>

我们也可以序列化querysets对象来代替model instances,因此在序列化的时候需要添加many=True参数

>>> serializer = SnippetSerializer(Snippet.objects.all(), many=True)
>>> serializer.data
[OrderedDict([('id', 1), ('title', ''), ('code', 'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', ''), ('code', 'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]

使用ModelSerializers

我们的SnippetSerializer类很多信息和Snippet model中是重复的,为了保证我们代码的简洁,减少重复代码,类似于django的提供的formmodelform,REST framework也提供了Serializerand ModelSerializer

下面使用ModelSerializer重构我们的serializer,重新打开serializers.py,使用下面代码替换掉SnippetSerializer

class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

serializers有一个不错的属性是,可以通过print函数来打印它 表示检查序列化实例中的所有字段

>>> from snippets.serializers import SnippetSerializer
>>> serializer = SnippetSerializer()
>>> print(repr(serializer))

重要的是要记住 ModelSerializer 不做任何格外的配置,它只是创建序列化类的快捷方式:

  • 根据model里的字段自动定义字段集
  • 简单的实现 create() and update() 方法

在django 视图中使用我们的Serializer

让我们看看我们如何使用我们新的Serializer类编写一些API视图。目前我们不使用任何REST框架的其他功能,我们只是将视图写为常规Django视图。

我们将开始通过创建一个HttpResponse子类用来返回任何形式的数据,如json;

编辑views.py

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):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs) @csrf_exempt
def snippet_list(request):
"""
列出所有的实例,或创建一个新的实例.
"""
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)

注意我们在post测试的时候无法获取到Django的csrf token,所以使用@csrf_exempt将此视图排除,不在检查csrf token

我们将还需要一个与单个代码段对应的视图,并且可以用来检索、更新和删除代码段

@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)

最后,我们需要配置url信息,在snippetapp下,新建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),
]

我们也需要在tutorial项目的urls.py下将snippetapp的url配置加载进去

from django.conf.urls import url, include

urlpatterns = [
url(r'^', include('snippets.urls')),
]

尝试测试我们的web api

启动我们的django server

python manage.py runserver

Performing system checks...

System check identified no issues (0 silenced).
February 04, 2017 - 08:38:55
Django version 1.10, using settings 'tutorial.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

最后使用curl 进行测试

curl -s http://127.0.0.1:8000/snippets/ | jq .
[
{
"id": 1,
"title": "",
"code": "foo = \"bar\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
},
{
"id": 2,
"title": "",
"code": "print \"hello, world\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
},
{
"id": 3,
"title": "",
"code": "print \"hello, world\"",
"linenos": false,
"language": "python",
"style": "friendly"
}
]

也可以指定id进行查询

curl -s http://127.0.0.1:8000/snippets/1/ | jq .
{
"id": 1,
"title": "",
"code": "foo = \"bar\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
}

源文参考:http://www.django-rest-framework.org/tutorial/1-serialization/#testing-our-first-attempt-at-a-web-api

django restframework 教程之Serialization(序列化)的更多相关文章

  1. django restframwork 教程之authentication权限

    当前我们的API在编辑或者删除的时候没有任何限制,我们不希望有些人有高级的行为,确保: 代码段始终与创建者相关联 只允许授权的用户可以创建代码段 只允许代码段创建者可以更新和删除 没有认证的请求应该有 ...

  2. django restframwork教程之Request和Response

    从这一篇文章开始,我们会覆盖整个REST framwork框架的核心,接下来让我们介绍一些基础的构建块 Request 对象 REST framework 引入了一个扩展HttpRequest的请求对 ...

  3. 测开大佬告诉你:如何5分钟快速创建restful风格的API接口-使用django restframework框架

    一.思考❓❔ 1.创建API接口难吗? 软件测试工程师: 只测过API接口, 从没创建过 应该需要掌握一门后端开发语言和后端开发框架吧!? 脑容量有限,想想就可怕 2.如何创建API接口呢? 使用Dj ...

  4. django restframework 序列化

    Serialization 序列化 创建表 from django.db import models from pygments.lexers import get_all_lexers from p ...

  5. django restframework serializer 增加自定义字段

    在使用django restframework serializer 序列化在django中定义的model时,有时候我们需要额外在serializer中增加一些model中没有的字段.有两种方法实现 ...

  6. django restframework

    一.django restframework 请求流程源码剖析 上面的认证一个流程是rest_framework的关于APIauth的认证流程,,这个流程试用权限.频率.版本.认证.这个四个组件都是通 ...

  7. Django Restframework 实践(一)

    具备以下知识: django http://www.cnblogs.com/menkeyi/p/5882464.html http://www.cnblogs.com/menkeyi/p/588245 ...

  8. rest-framework框架——APIView和序列化组件

    一.快速实例 Quickstart http://www.cnblogs.com/yuanchenqi/articles/8719520.html restful协议 ---- 一切皆是资源,操作只是 ...

  9. django restframework 的日常使用

    本文讨论 django restframework 的日常使用,满足常用 api 编写的需求,比如 List, Detail, Update, Put, Patch 等等.探讨 django rest ...

随机推荐

  1. centos7+ docker1.12 实践部署docker及配置direct_lvm

    前言 Docker现在在后端是那么的火热..尤其当笔者了解了docker是什么.能做什么之后,真的是感觉特别的exciting,便迫不及待的去实践部署一下. 但是在实际部署中,因为笔者使用的是阿里云e ...

  2. javaScript之function定义

    背景知识 函数定义 在javaScript中,function的定义有3种: 1.匿名定义                function(){} 2.非匿名定义                fun ...

  3. 关于PHP开发所需要的工具和环境

    0.notepad++ 一个类型记事本的软件,用来看安装的部署说明命令. 1.虚拟机 在虚拟机里面操作,本机不会被影响. 2.CentOS系统 类似Linux的系统,在里面安装PHP,Nginx,ph ...

  4. opencv3.2 dnn 图像分割

    下载 http://dl.caffe.berkeleyvision.org/fcn32s-heavy-pascal.caffemodel 在opencv_contrib-3.2.0/modules/d ...

  5. 【转】【C#】ZIP、RAR 压缩与解压缩

    压缩文件夹 源码如下 using System; using System.Data; using System.Configuration; using System.Web; using Syst ...

  6. e684. 以多种格式打印

    A Book object is used when printing pages with different page formats. This example prints the first ...

  7. e650. 激活事件

    An object wishing to fire item events must implement ItemSelectable. This example shows typical code ...

  8. 11个超棒的 jQuery 分步指引插件(转)

    当一个网站或者一个Web应用推出新功能时,为了让用户了解你的站点(或应用)如何操作,往往都会在站点(应用)中添加一个分步指引的效果.然而这样的效果,对于不懂原生JS的同学来说,是件很头痛的事情. 下面 ...

  9. asp.net管线

  10. 解决 SharePoint 2010 拒绝访问爬网内容源错误的小技巧(禁用环回请求的两种方式)

    这里有一条解决在SharePoint 2010搜索爬网时遇到的“拒绝访问错误”的小技巧. 首先要检查默认内容访问帐户是否具有相应的访问权限,或者添加一条相应的爬网规则.如果目标资源库是一个ShareP ...