用tornado写一个博客(3)数据库与路由

2015-10-17 15:26:51

本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议

上次我们讲了如何使用 tornado 自带的模板进行html的后端渲染。让每一个打在前端的html网页都不一样,

但是!突然发现,我们想写一个博客,这样做,我们输入的东西一下子就消失了,因为这些数据根本没有存储在数据库里面啊!!

那么我们要怎么做才能让他们存储在数据库中呢???

通常我们接触的数据库,最多的无外乎在社交网络上,社交网络的后台的数据库要存储大量的用户数据,如好友,组群,权限,图片,评论等等等等,但是有一个问题,就是社交网络的数据们之间的关系太强了,比如这个用户和另一个用户是好友关系,设想,如果每一个用户的在后台查找都需要迭代一次数据库的数据,那么这样做效率太低,数据库会发生问题的,其实很早就有人发现了这个问题,当时有人发表论文讨论这个问题,而后关系型数据库应运而生

我们常用的关系型数据库有 MysqlOraclepostgresql等等,而这个博客就是基于 Mysql的,

但是关系型数据库虽好,但也会因为他重视关系而使得某些设计受制,所以导致性能的下降,例如像游戏,量化交易之类的极需要性能的数据库操作密集的应用就很麻烦

所以非关系型数据库也开始火起,其中 MongoDB就是其中之一

pic

今天我们就用MongoDB做我们应用的数据库,MongoDB最近非常的火,首先他的性能非常又一,另外他采用类是json的文件保存格式bson,这个保存格式和json很像,也和python的 dict格式很相近,都是 KEY:VALUE型的,表达起来非常舒服,比什么xml好看多了

使用MongoDB写一个博客


首先,你先安装好你的MongoDB

然后因为我们是使用python操控mongodb,所以需要安装 pymongo来通过python代码操作mongodb:

安装 pymongo

pip install pymongo

pymongo的具体操作请看他的文档:

http://api.mongodb.org/python/current/tutorial.html

首先我们就来看看我们今天需要用到的 pymongo的操作:

链接mongodb(默认配置的,如果没改,就是用这个)

client=pymongo.ClientMongo("localhost",27017)

链接我们的数据库

db=client['db_name']

链接我们要的集合

con=db['collection_name']

这样我们就可以对这个集合进行数据库操作了

插入数据,并设置独一无二的id,

注意,这里的data必须是字典的键值对形式

con.insert_one(data).inserted_id

查找所有数据,他会返回一个集合

con.find()

用某些限制条件查询数据,他会返回一个数据集合,如这个就会返回 name为aljun的那个数据

这个需要注意,如果你存储时是 int那么搜索也必须是同种数据,不然会出错

con.find_one("name":"aljun")

得到集合量的个数

con.find().count()

好了,有了这些操作,足够我们写一个博客了

实战,书写一个简单博客


首先我们先建立一个我们的html前端代码,新建一个 index.html,并写入:

<!DOCTYPE html>
<html>
<head>
    <title>blog home</title>
</head>
<body>
<div style="width:700px;border:2px solid #7E3D76">
    <h1 style="color:#613030">write down your blog!</h1>
    <div id="form">
        <form action="" method="post">
            <p>editor:</p>
            <input type="text" name="editor">
            <p>body:</p>
            <input type="text" name="body">
            <p></p>
            <input type="submit" value="submit">
        </form>
    </div>
    <hr>
    <h3 style="color:#613030">blog list:</h3>
    <div id="blog_list">
        {% for blog in blogs%}
        <div style="margin:3px;border:2px solid #FFDAC8;border-left:0px;border-right:0px;">
            <p>editpr:</p>
            <p>{{ blog['editor'] }}</p>
            <p>blog:</p>
            <p>{{ blog['body'] }}</p>
        </div>
        {% end %}
    </div>
</div>
</body>
</html>

鉴于我们上一篇已经讲好了 tornado的模板了,所以这个理解起来很容易,我们使用表单方法为post来传递信息,然后在下面把后台传过来的数据都打出来

好了,我们新建我们的 tornado文件db_url.py,并写入:

import tornado.ioloop
import pymongo
import tornado.web

port=3000
Mongo_url="localhost"
Mongo_port=27017
db_name="blog"
con_name="blog"

class BlogHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.client=pymongo.MongoClient(Mongo_url,Mongo_port)
        self.db=self.client[db_name]
        self.con=self.db[con_name]

    def get(self):
        blogs=self.con.find()
        self.render("index.html",blogs=blogs)

    def post(self):
        editor=self.get_argument("editor")
        body=self.get_argument("body")
        self.con.insert_one({"editor":editor,"body":body}).inserted_id
        self.redirect("/")

def init_app():
    print "app is running on http://127.0.0.1:%s" % port
    return tornado.web.Application([
        tornado.web.url(r"/",BlogHandler)
    ])

if __name__=="__main__":
    app=init_app()
    app.listen(port)
    tornado.ioloop.IOLoop.current().start()
  • 这里我们先定义好一些常量,比如数据库名字,端口名字等等

  • 然后我们使用 RequestHandler提供的初始化函数,因为如果使用python的内置的 __init __会报错,所以使用tornado 自己提供的,这里我们初始化了数据库

  • 接着,当访问我们的 get 方法时对 MongoDB进行一次全部查找,把所有的数据库信息都拿出来

  • 然后我们书写我们的 post 方法,我们接受传过来的参数,然后存储进 mongodb数据库

  • 因为其他的我们之前都说过了,所以就不用多说了,好了我们简单的一个博客写出来了

这时我们可以在终端输入 :

python db_url.py

然后用浏览器打开这个网址 http://127.0.0.1:3000,我们就可以看到:

pic

然后我们输入些信息,单击 submit

pic

我们就可以看到:

pic

这样我们的一个简单的博客就完成了,是不是值得庆祝一下!!!!!

路由系统


其实我们这里发现了,如果这样写下去,我们只能使用有限的网址来做我们的请求反问,但是,反观豆瓣,淘宝等等网站,我们都会发现,他们有大量的网页

例如豆瓣电影的这个网址路径:

pic

我们可以看到他是在 http://movie.douban.com/subject/26588970/ 这个路径后面个了一串的数字码,其实这个是一种简单的分页操作,因为以后网页会像图书馆的书那么多,所以你需要给每个网页和书一样的管理 id,这样便于查找

Tornado在元组中使用正则表达式来匹配HTTP请求的路径。(这个路径是URL中主机名后面的部分,不包括查询字符串和碎片。)Tornado把这些正则表达式看作已经包含了行开始和结束锚点(即,字符串"/"被看作为"^/$")。

关于正则表达式,请自行google

好了,现在我们先新建一个html文件,来打出我们的没一个博客内容,新建 archive.html并写入:

<!DOCTYPE html>
<html>
<head>
    <title>post</title>
</head>
<body>
    <h1 style="color: #6C3365">the blog:</h1>
    <p >from:{{ blog['editor'] }}</p>
    <p>body:</p>
    <p>{{ blog['body'] }}</p>
</body>
</html>

好的,现在我们来改写我们的 db_url.py,给每一个博客增加一个计数:

...
class BlogHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.client=pymongo.MongoClient(Mongo_url,Mongo_port)
        self.db=self.client[db_name]
        self.con=self.db[con_name]

    def get(self):
        blogs=self.con.find()

        self.render("index.html",blogs=blogs)

    def post(self):
        editor=self.get_argument("editor")
        body=self.get_argument("body")
        index=int(self.con.find().count())+1
        self.con.insert_one({"editor":editor,"body":body,"index":index}).inserted_id
        self.redirect("/")

class ArchiveHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.client=pymongo.MongoClient(Mongo_url,Mongo_port)
        self.db=self.client[db_name]
        self.con=self.db[con_name]
    def get(self,index):
        index=int(index)
        blog=self.con.find_one({"index":index})
        self.render("archive.html",blog=blog)

def init_app():
    print "app is running on http://127.0.0.1:%s" % port
    return tornado.web.Application([
        tornado.web.url(r"/",BlogHandler),
        tornado.web.url(r"/archive/(\d+)",ArchiveHandler),
    ])
...
  • 这里我们给每一个博客一个递增的 index作为博客的索引,用的是计算每个集合里面的个数,然后加一的简单算法

  • 然后我们多写了一个 ArchiveHandler,用来做每一个博客的处理handler,简单的就是从数据库里面查询,然后拿出来

  • 最后看到我们的我们的 init_app方法那里改了 ,这里增加了一个 /archive/(d+)最后的这个 (\d+)正则表达式的结果就是匹配任意数字,这里匹配的数字结果会传递给handler的get函数的第一个参数,可以看到就是我们 ArchiveHandler的get方法的地一个参数 index

  • 这样我们就可以任意的传给blog他自己的id,也好进行查询了

接着我们改写我们的 index.html来给没一个博客增加一个链接:

<<!DOCTYPE html>
<html>
<head>
    <title>blog home</title>
</head>
<body>
<div style="width:700px;border:2px solid #7E3D76">
    <h1 style="color:#613030">write down your blog!</h1>
    <div id="form">
        <form action="" method="post">
            <p>editor:</p>
            <input type="text" name="editor">
            <p>body:</p>
            <input type="text" name="body">
            <p></p>
            <input type="submit" value="submit">
        </form>
    </div>
    <hr>
    <h3 style="color:#613030">blog list:</h3>
        <div id="blog_list">
        {% for blog in blogs%}
            <div style="margin:3px;border:2px solid #FFDAC8;border-left:0px;border-right:0px;">
            <p>editpr:</p>
            <p>{{ blog['editor'] }}</p>
            <p>blog:</p>
            <p>{{ blog['body'] }}</p>
            <a href="/archive/{{ blog['index'] }}">link</a>
            </div>
        {% end %}
         </div>
</div>
</body>
</html>

我们给每一个博客增加了一个链接,链接到 /archive/{{ blog['index'] }}

好,话不多说,我们跑跑看我们的程序:

python db_url.py

然后打开浏览器,网址为 127.0.0.1:3000,就可以看到:

pic

然后我们输入一个,之后点击submit:

pic

然后我们就可以看到:

pic

然后,我们可以点击那个 link,就可以看到:

pic

好了,这样我们的博客的每一个分页就算是做好,是不是可喜可贺,综合上我上次讲的,写出一个博客就算是完全没有问题了!!!

同样的,我们的源码都会在这里:

https://github.com/salamer/tornado_blog

tornado 返回首页

Designed and built with all the love in the world by the Mr.ALJUN.

@SERVER BY NGINX AND POWER BY DIGITALOCEAN.

© COPYRIGHT BY GAGASALAMER 2015