Day 25: 联合Tornado、MongoDB 和 AngularJS 进行应用开发

编者注:我们发现了有趣的系列文《30天学习30种新技术》,正在翻译,一天一篇更新,年终礼包。下面是第23天的内容。


今天的《30天学习30种新技术》,我决定暂时放下 JavaScripts 的内容,而去学习一个叫做 Tornado 的 Web 框架。我决定去学 Tornado 的原因是我这样就可以用 Python 去写 Web 程序了。我只学过 Flask 框架,所以我觉得 Tornado 应该能增加我在 Python Web 开发方面的知识。我们在这篇博文中描述的应用使用 Tornado 来作 REST 后端,MongoDB 作为数据库,AngularJS 作为客户端那边的 JavaScripts MVC 框架,然后 OpenShift 作为部署的平台。

Day 25: 联合Tornado、MongoDB 和 AngularJS 进行应用开发

什么是 Tornado?

Tornado 是一个开源的 Python Web 框架,是一个非阻塞(non blocking)的的 Web 服务器, 最开始是在 FriendFeed开发的。在 FriendFeed 被收购之后,Facebook 维护并继续发展 Tornado。由于它的非阻塞网络输入输出(non-blocking network I/O )特性,它有卓越的可扩展性,能同时支持一千多个连接。


应用案例

在这篇博文中,我们将会开发一个允许用户发布和分享链接的社交化书签应用。你可以在这里看到真实在 OpenShift 上运行着的程序。这是我们在 Day 22 开发过的应用,所以可以参考那篇博文以便更好地理解这个应用案例。


GitHub 仓库

今天这个演示应用的代码可以在 GitHub 上得到:day25-tornado-demo-app


前期准备

在我们开始 Tornado 之前,我们需要在机器上安装 Pythonvirtualenv。在这篇博文中,我使用的 Python 版本是 2.7

这个应用使用 MongoDB 作为数据存储的软件,所以请下载对应你所用操作系统的最新的 MongoDB 发行版


开发 Tornado MongoDB 应用

我们会使用 pip 安装 Tornado。对于那些不熟悉 pip 的开发者,其实 pip 就是一个 Python 的包管理器。我们可以从官网安装 pip。打开终端,转到任何一个在文件系统上方便的目录,然后运行下面的命令:

$ mkdir getbookmarks

$ cd getbookmarks

$ virtualenv venv --python=python2.7

$ . venv/bin/activate

$ pip install tornado

$ pip install pymongo

上面的命令会在本机上创建一个 getbookmarks 目录,然后在 Python 2.7 下激活 virtualenv,然后安装 tornado 包,最后安装 pymongo。其中,pymongo 是官方 MongoDB 的 Python 驱动;我们会使用它往 MongoDB 中写入故事(stories)。

在 getbookmarks 目录下,创建一个名为 getbookmarks.py 的文件:

$ touch getbookmarks.py

复制下面的代码,然后粘贴到 getbookmarks.py 源文件中:

import os

from tornado import ioloop,web

from pymongo import MongoClient

import json

from bson import json_util

from bson.objectid import ObjectId

class IndexHandler(web.RequestHandler):

    def get(self):

        self.write("Hello World!!")

settings = {

    "template_path": os.path.join(os.path.dirname(__file__), "templates"),

    "static_path": os.path.join(os.path.dirname(__file__), "static"),

    "debug" : True

}

application = web.Application([

    (r'/', IndexHandler),

    (r'/index', IndexHandler),

],**settings)

if __name__ == "__main__":

    application.listen(8888)

    ioloop.IOLoop.instance().start()

上面的代码会执行下面的事情:

1. 我们从导入需要的库开始;

2. 下一步,我们定义一个扩展类 web.RequestHandler 的新类:IndexHandler。一个 Tornado web 应用会把 URLs 或者 URL 模式对应到 web.RequestHandler 的子类。这些类定义了 get()post() 等方法去处理访问这个 URL 的 HTTP GET 或者 POST 请求。当在地址 '/' 下收到一个 GET 请求时,IndexHandler 会返回一个 "Hello World!!"

3. 接着我们定义了一些应用的设置。template_path 设置是告诉 Tornado 应用在 template 目录寻找应用模板。static_path 设置告诉应用使用 static 目录里面的类似 css、图像、javascript 文件等静态文件。通过设置 debugTrue,你对项目做了改变后,会自动重载,不用重启查看效果。我们会在应用开发过程中,保持着调试器在后台运行。这能提供高效的开发环境。

4. 接着,我们创建一个Tornado 应用实例,把路由routes)和 settings 传递进去。

5. 最后,我们使用 python getbookmarks.py 命令启动服务器去运行这个应用

打开 http://localhost:8888http://localhost:8888/index 看看是否看到 "Hello World!!"


配置 MongoDB

在导入库之后,增加下面的语句:

MONGODB_DB_URL = os.environ.get('OPENSHIFT_MONGODB_DB_URL') if os.environ.get('OPENSHIFT_MONGODB_DB_URL') else 'mongodb://localhost:27017/'

MONGODB_DB_NAME = os.environ.get('OPENSHIFT_APP_NAME') if os.environ.get('OPENSHIFT_APP_NAME') else 'getbookmarks'

client = MongoClient(MONGODB_DB_URL)

db = client[MONGODB_DB_NAME]

我们定义了 MongoDB 连接的路由和数据库的名称。如果应用是部署到 OpenShift 上,那么 OpenShift 特定环境变量会先被使用,如果没有,就会使用本机上的配置。

我们创建了一个 MongoClient 实例,把连接的路由传递进去。这个连接路由是只想运行着的 mongod 实例。接着我们使用 MongoClient 实例使用数据库


创建和列出所有的故事(Stories)

现在我们要添加创建新的故事(stories)和列出所有故事(stories)的功能。我们首先把路由加到下面的应用实例中:

application = web.Application([

    (r'/', IndexHandler),

    (r'/index', IndexHandler),

    (r'/api/v1/stories',StoriesHandler),

],**settings)

接着,我们定义一个把故事(stories)保存在 MongoDB 和在里面查找所有故事(stories)的 StoriesHandler:

class StoriesHandler(web.RequestHandler):

    def get(self):

        stories = db.stories.find()

        self.set_header("Content-Type", "application/json")

        self.write(json.dumps(list(stories),default=json_util.default))

    def post(self):

        story_data = json.loads(self.request.body)

        story_id = db.stories.insert(story_data)

        print('story created with id ' + str(story_id))

        self.set_header("Content-Type", "application/json")

        self.set_status(201)

在上面的代码中:

1. 当一个用户发出一个 GET 请求到 /api/v1/stories 时,我们会向 MongoDB 中发出一个 Find() 方法请求。由于我们没有具体声明是任何查询,所以它会从 MongoDB 取出所有的故事。我们把内容类型(content type)设置为 application/json,然后转出(dump) json 回应。

2. 当用户发出一个 POST 请求到 /api/v1/stories,然后我们首先解码 json 的内容到一个字典(dictionary),然后把数据写入 MongoDB。我们会把回应状态(response status)设为 201(已创建)。


查看单独的故事(story)

最后一个后端功能是查看单独的故事,我们首先指明路由:

application = web.Application([

    (r'/', IndexHandler),

    (r'/index', IndexHandler),

    (r'/api/v1/stories',StoriesHandler),

    (r'/api/v1/stories/(.*)', StoryHandler)

],**settings)

我们编写 StoryHandler

class StoryHandler(web.RequestHandler):

    def get(self , story_id):

        story = db.stories.find_one({"_id":ObjectId(str(story_id))})

        self.set_header("Content-Type", "application/json")

        self.write(json.dumps((story),default=json_util.default))

上面的代码查找对应 story_id 的故事,然后转出 json 回应。


AngualarJS 前端

我决定重用我在 第 22 天 写的前端。第 22 天的内容展示了如何以 Java Spring 框架作为后端去使用 AngularJS。使用 JavaScripts MVC 架构的最好的地方就是你可以重用前端的代码,如果你的应用符合 REST 接口客户端的要求。可以阅读第 22 天的内容了解更多。

你可以在我的 GiHub 仓库下载 AngularJS 前端。复制静态文件和模板文件夹,粘贴到 getbookmarks.py 所在文件夹。


部署应用到 OpenShift

在构建应用之前,我们需要做些设置:

  1. 注册一个OpenShift账号。注册是完全免费的,Red Hat给每个用户三枚免费的Gear,可以用Gear运行你的应用。在写作此文的时候,每个用户能免费使用总共 1.5 GB 内存和 3 GB 硬盘空间。
  2. 安装 rhc客户端工具rhc是ruby gem,因此你的机子上需要装有 ruby 1.8.7以上版本。 只需输入 sudo gem install rhc即可安装 rhc 。如果你已经安装过了,确保是最新版。运行sudo gem update rhc即可升级。关于配置rhc命令行工具的详细信息,请参考: https://openshift.redhat.com/community/developers/rhc-client-tools-install
  3. 使用 rhc 的 setup 命令配置你的 OpenShift 账号。这个命令会帮助你创建一个命名空间,同时将你的ssh公钥上传至 OpenShift 服务器。


部署应用

输入如下命令即可将应用部署到 OpenShift:

$ rhc create-app day25demo python-2.7 mongodb-2 --from-code https://github.com/shekhargulati/day25-tornado-demo-app.git

这个命令将创建应用,设置公开的DNS,创建私有git仓库,最后利用你的Github仓库中的代码来部署应用。应用可以通过 http://day25demo-shekhargulati.rhcloud.com/#/ 访问。

上一篇:自动化测试如何解决验证码的问题


下一篇:MySQL · 捉虫动态 · left-join多表导致crash