virtualenv is a tool to create isolated Python environments.

建立一个新的环境

Before we do anything else we'll create a new virtual environment, using virtualenv. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.

#操作virtualenv

ubuntu@ubuntu:~/tutorial$ sudo pip install virtualenv
ubuntu@ubuntu:~/tutorial$ virtualenv env
Running virtualenv with interpreter /usr/bin/python2 #这里默认启动py2,要想启动py3需要切换到py3的目录
错误... ubuntu@ubuntu:~/tutorial$ cd /usr/lib/python3/dist-packages
ubuntu@ubuntu:/usr/lib/python3/dist-packages$ ls env
bin lib local pip-selfcheck.json share
ubuntu@ubuntu:/usr/lib/python3/dist-packages$ cd env/bin
ubuntu@ubuntu:/usr/lib/python3/dist-packages/env/bin$ source activate #激活virtualenv
(env) ubuntu@ubuntu:~$ deactivate #释放virtualenv
ubuntu@ubuntu:~$

# 激活virtualenv

virtualenv env
source env/bin/activate

Now that we're inside a virtualenv environment, we can install our package requirements.

# 安装所需模块

pip3 install django
pip3 install djangorestframework
pip3 install pygments # We'll be using this for the code highlighting

Note: To exit the virtualenv environment at any time, just 键入deactivate. For more information see the virtualenv documentation.

入门

摘要:入门部分创建了一个Django项目。

Okay, we're ready to get coding. To get started, let's create a new project to work with.

# Linux下创建一个项目

cd ~
django-admin.py startproject tutorial
cd tutorial #结果:
ubuntu@ubuntu:~$ tree tutorial
tutorial
├── manage.py
└── tutorial
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py 1 directory, 5 files

Once that's done we can create an app that we'll use to create a simple Web API.

# 创建一个app

python3 manage.py startapp snippets

#结果:
ubuntu@ubuntu:~$ tree tutorial
tutorial
├── manage.py
├── snippets
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── tutorial
├── __init__.py
├── __pycache__
│   ├── __init__.cpython-35.pyc
│   └── settings.cpython-35.pyc
├── settings.py
├── urls.py
└── wsgi.py 4 directories, 14 files

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 = (
...
  'snipppets',
'rest_framework',
)

Please note that if you're using Django <1.9, you need to replace snippets.apps.SnippetsConfig with snippets.

Okay, we're ready to roll.

创建一个可以使用的model

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. Note: Good programming practices include comments. Although you will find them in our repository version of this tutorial code, we have omitted them here to focus on the code itself.

# models.py

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',) #排序字段

We'll also need to create an initial migration for our snippet model, and sync the database for the first time.

# 初始化数据库

python3 manage.py makemigrations snippets
python3 manage.py migrate

(不用)创建一个Serializer类

The first thing we need to get started on our Web API is to provide a way of 序列化和反序列化 the snippet instances into representations such as json. We can do this by declaring serializers that work very similar to Django's forms. Create a file in the snippets directory named serializers.py and add the following.

#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):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
return Snippet.objects.create(**validated_data) def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
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

the serializer class 的第一部分定义了序列化/反序列化的字段。The create() and update()methods define how fully fledged instances are created or modified when calling serializer.save()

serializer class 与 Django的 Form class 非常相似, 并且包含类似的验证标记, such as requiredmax_length and default.

在某些情况下,the field flags还可以控制serializer的显示方式,比如渲染html页面. 上面的 {'base_template': 'textarea.html'} 就相当于Django-Form 中的 widget=widgets.Textarea. 这对于控制可浏览API的显示方式特别有用,我们将在本教程的后面看到。

实际上,我们也可以使用 the ModelSerializer class 来节省一些时间 , 但是现在我们将保留这种serializer定义。

使用Serializers串行器

摘要:这一部分都是在python shell下操作的,进行序列化和反系列化操作。

在我们进一步了解之前,让我们熟悉一下Serializer类的使用。让我们进入Django shell。

# python shell下

python 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') #实例化一个对象并填写code字段,然后保存。
snippet.save() snippet = Snippet(code='print "hello, world"\n')
snippet.save()

现在我们已经有了几个片段实例。我们来序列化其中一个实例。

serializer = SnippetSerializer(snippet)   #snippet是Snippet class的对象
serializer.data # {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'} type(serializer.data) #<class 'rest_framework.utils.serializer_helpers.ReturnDict'>,不是python原生数据类型。

此时,我们将model实例转换为Python原生数据类型。为了完成序列化过程,我们先将数据转化为json

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

反序列化是类似的. 首先我们将一个流解析为Python原生数据类型...

from django.utils.six import BytesIO

stream = BytesIO(content)

type(stream)                           #<class '_io.BytesIO'>
data = JSONParser().parse(stream) type(data) #<class 'dict'>,python原生数据类型。

小结:

实例化:snippet = Snippet(code='foo = "bar"\n')
序列化:serializer = SnippetSerializer(snippet)

因为serializer.data不是python原生数据类型(<class 'rest_framework.utils.serializer_helpers.ReturnDict'>)
要想转为python原生数据类型需要两个中间步骤:
      转为json:content = JSONRenderer().render(serializer.data)
      转为BytesIO:stream = BytesIO(content)
转为原生数据类型:data = JSONParser().parse(stream)

...然后我们将这些原生数据类型恢复到 a fully populated object instance。

serializer = SnippetSerializer(data=data)   #data是python原生数据类型。
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>

请注意,API 与 forms 很相似。当我们使用serializer编写视图函数时,相似性会更加明显。

我们也可以序列化 querysets 而不是 model instances. 为了做到这一点, 我们仅仅添加 a many=True flag to the serializer arguments.

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复制了Snippet中的大量信息。如果可以保持代码更简洁,那将是很好的。

与Django提供Form类和ModelForm类的方式相同,REST框架包括Serializer类和ModelSerializer类。

让我们来看看使用ModelSerializer类重构我们的serializer。再次打开文件 snippets/serializers.py , and replace the SnippetSerializer class with the following.

from snippets import models
from rest_framework import serializers class SnippetSerializer(serializers.ModelSerializer): #之前继承的是serializers.Serializer
class Meta:
model = models.Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

serializers有一个很好的属性是你可以检查一个serializer instance的所有字段, by printing its representation. 打开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类不会做任何特别神奇的事情,它们只是创建 serializer classes 快捷方式:

  • 自动确定具有的字段。
  • 默认实现create()update()方法。

(不用,在第二篇加了format)使用Serializer编写常规的Django视图

让我们来看看该如何使用Serializer类来编写一些API视图。目前我们不会使用任何REST框架的其他功能,我们只编写一些常规的Django视图函数。

编辑 snippets/views.py文件,并添加以下内容。

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

The root of our API 将是一个视图,它支持列出所有现有的片段,或创建一个新的片段。

@csrf_exempt
def snippet_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
snippets = Snippet.objects.all() #querysets
serializer = SnippetSerializer(snippets, many=True) #序列化querysets,many=True
return JsonResponse(serializer.data, safe=False) #safe=False,是啥??? elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data) #SnippetSerializer中有data???
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)

请注意,因为我们希望能够从不具有CSRF token的客户端以POST方法访问此视图函数,因此我们需要用csrf_exempt标记视图。这不是你通常想要做的事情,REST框架视图实际上使用比这更有明显的行为,但它现在将用于我们的目的。

我们还需要一个与 an individual snippet对应的视图,并可用于检索,更新或删除the snippet。

@csrf_exempt
def snippet_detail(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
snippet = Snippet.objects.get(pk=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)

最后我们需要把这些视图函数连接起来。创建snippets/urls.py文件:

#app下面的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文件中连接根urlconf ,以包含我们的片段应用程序的URL。

from django.conf.urls import url, include

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

It's worth noting that there are a couple of edge cases we're not dealing with properly at the moment. If we send malformed json, or if a request is made with a method that the view doesn't handle, then we'll end up with a 500 "server error" response. Still, this'll do for now.

测试我们在Web API上的第一次尝试

现在我们可以启动一个运行我们的代码片段的示例服务器。

退出shell...

quit()

...and start up Django's development server.

python manage.py runserver 192.168.66.250:9000

Validating models...

0 errors found
Django version 1.11, using settings 'tutorial.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Notes:在settings.py中添加ALLOWED_HOSTS = {'192.168.66.200',}

在另一个终端窗口中,我们可以测试服务器。

我们可以使用curlhttpie来测试我们的API 。Httpie是用Python编写的用户友好的http客户端。我们来安装它。

您可以使用pip安装httpie:

#

pip install httpie

最后,我们可以得到所有片段的列表:

#

http http://127.0.0.1:8000/snippets/

HTTP/1.1 200 OK
...
[
{
"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来获取特定的代码段:

#

http http://127.0.0.1:8000/snippets/2/

HTTP/1.1 200 OK
...
{
"id": 2,
"title": "",
"code": "print \"hello, world\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
}

同样,您可以通过在网络浏览器中访问这些URL来显示相同​​的json。

API(一)之Serialization的更多相关文章

  1. Jersey(1.19.1) - Client API, Ease of use and reusing JAX-RS artifacts

    Since a resource is represented as a Java type it makes it easy to configure, pass around and inject ...

  2. 使用 Node.js 搭建API 网关

    外部客户端访问微服务架构中的服务时,服务端会对认证和传输有一些常见的要求.API 网关提供共享层来处理服务协议之间的差异,并满足特定客户端(如桌面浏览器.移动设备和老系统)的要求. 微服务和消费者 微 ...

  3. .Net 读取配置文件 xml

    直接解析XML文件 1.System.Xml.Linq命名空间下提供可以使用linq查询的类,使用linq to xml读取也很方便. 2.还可以使用System.Xml.Serialization类 ...

  4. 【资源大全】.NET资源大全中文版(Awesome最新版)

    算法与数据结构(Algorithms and Data structures) 应用程序接口(API) 应用程序框架(Application Frameworks) 模板引擎(Application ...

  5. 使用示例带你提前了解 Java 9 中的新特性

    使用示例带你提前了解 Java 9 中的新特性 转载来源:https://juejin.im/post/58c5e402128fe100603cc194 英文出处:https://www.journa ...

  6. [翻译] Working with NSURLSession: AFNetworking 2.0

    Working with NSURLSession: AFNetworking 2.0   简单翻译,有很多错误,看官无法理解处请英文原文对照. http://code.tutsplus.com/tu ...

  7. Laravel手记:执行route:cache时报LogicException

    laravel5的路由支持缓存.需要执行以下命令: php artisan route:cache 执行完毕后,报出以下错误: Route cache cleared! [LogicException ...

  8. 大数据查询——HBase读写设计与实践--转

    背景介绍 本项目主要解决 check 和 opinion2 张历史数据表(历史数据是指当业务发生过程中的完整中间流程和结果数据)的在线查询.原实现基于 Oracle 提供存储查询服务,随着数据量的不断 ...

  9. Avro使用手册

    1. Overview Data serialization is a technique of converting data into binary or text format. There a ...

随机推荐

  1. javascript arguments介绍

    来源于: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments https://g ...

  2. Android——RatingBar(评价条)相关知识总结贴

    android用户界面之RatingBar教程实例汇总 http://www.apkbus.com/android-51346-1-1.html Android 中文 API (40) —— Rati ...

  3. xcode9 报错 “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift

    用xcode编译后会出现这个错误的情况: 1.使用cocopod导入第三方swift包后,swift的包是比较老的swift开发的. 2.用xcode9 打开老的swift(比如swift2.0)的工 ...

  4. 【Linux】top命令

    top命令经常用来监控linux的系统状况,比如cpu.内存的使用,程序员基本都知道这个命令,但比较奇怪的是能用好它的人却很少,例如top监控视图中内存数值的含义就有不少的曲解.本文通过一个运行中的W ...

  5. HDU 3277 Marriage Match III(并查集+二分答案+最大流SAP)拆点,经典

    Marriage Match III Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  6. Atiit 常见功能 常用功能与模块的最快速解决方案

    Atiit 常见功能 常用功能与模块的最快速解决方案 一.大力使用第三方API接口 一.导出excel jquery.table2excel 二.Form表单验证,使用h5验证属性 验证发生在form ...

  7. windows下安装pycharm并连接Linux的python环境

    1. 下载安装Pycharm专业版 具体方法略.Pycharm5激活方法参考http://www.cnblogs.com/snsdzjlz320/p/7110186.html 2. 添加配置连接远程服 ...

  8. LeetCode: Best Time to Buy and Sell Stock III 解题报告

    Best Time to Buy and Sell Stock IIIQuestion SolutionSay you have an array for which the ith element ...

  9. Stanford Corenlp学习笔记——词性标注

    使用Stanford Corenlp对中文进行词性标注 语言为Scala,使用的jar的版本是3.6.0,而且是手动添加jar包,使用sbt添加其他版本的时候出现了各种各样的问题 添加的jar包有5个 ...

  10. Tensorflow学习笔记——安装和运行

    参考的资料: 1.官网 2.tensorflow官方文档中文版 安装的是Python 2.7; CPU support (no GPU support),版本是1.1 pip install tens ...