Tornado学习笔记第四篇-aiomysql完成留言板功能

这篇我们使用Torando实现一个留言板的功能,和之前学习Django一样。

image-20181106164504031

新增数据库message数据表message

image-20181106155735073

tornado中读取MySQL数据需要使用使用支持异步的驱动,我们使用的是aiomysql

因为aiomysql的底层是基于asyncio的,所以可以直接在tornado中使用(需要时python3+的环境)。

aiomysqlgithub地址

我们看下使用SQL语言的Basic Example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from aiomysql import create_pool


async def go():
# 创建链接是耗时的 IO 操作
async with create_pool(host='127.0.0.1', port=3306,
user='root', password='root',
db='message', charset="utf8") as pool:

# acquire 也是涉及到 socket 的
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# execute 是需要等待的
await cur.execute("SELECT * from message")
value = await cur.fetchone()
print(value)
# 从socket 中取数据 网络耗时 都是需要 await


if __name__ == "__main__":
from tornado import ioloop
# 这个 ioloop 是单例模式 我们使用 tornado 的 ioloop

io_loop = ioloop.IOLoop.current()
# 上面定义的是协程因此我们需要协程的调用方式
io_loop.run_sync(go)

上面是单独使用的,我们集成到tornado中使用。

首先是设置数据库。

1
2
3
4
5
6
7
8
9
10
11
12
settings = {
"static_path": "static",
"static_url_prefix": "/static/",
"template_path": "templates",
"db": {
"host": "127.0.0.1",
"user": "root",
"password": "root",
"name": "message",
"port": 3306
}
}

那怎么将设置的db配置到链接中呢?

1
2
3
4
5
6
7
if __name__ == "__main__":
app = web.Application([
("/", MainHandler, {"db": settings["db"]}),
("/static/(.*)", StaticFileHandler, {"path": "static"})
], debug=True, **settings)
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

我们使用初始化方法在initialize中设置,通过传递参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MainHandler(web.RequestHandler):
def initialize(self, db):
self.db = db

async def get(self, *args, **kwargs):
id = ""
name = ""
email = ""
address = ""
message = ""
async with create_pool(host=self.db["host"], port=self.db["port"],
user=self.db["user"], password=self.db["password"],
db=self.db["name"], charset="utf8") as pool:
async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute("SELECT id, name, email, address, message from message")
try:
id, name, email, address, message = await cur.fetchone()
except Exception as e:
pass
self.render("message.html", id=id, email=email, name=name, address=address, message=message)

这样子我们就完成个一个页面获取值,返回到模板。

现在使用form表单提交修改数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
async def post(self, *args, **kwargs):
id = self.get_body_argument("id", "")
name = self.get_body_argument("name", "")
email = self.get_body_argument("email", "")
address = self.get_body_argument("address", "")
message = self.get_body_argument("message", "")

async with create_pool(host=self.db["host"], port=self.db["port"],
user=self.db["user"], password=self.db["password"],
db=self.db["name"], charset="utf8") as pool:
async with pool.acquire() as conn:
async with conn.cursor() as cur:
if not id:
await cur.execute(
"INSERT INTO message(name, email, address, message) VALUES('{}','{}','{}','{}')".format(name,
email,
address,
message))
else:
await cur.execute("update message set name='{}', email='{}', address='{}', message='{}'".format(name, email, address, message))
await conn.commit()
self.render("message.html", id=id, email=email, name=name, address=address, message=message)

我们使用get_body_argument获得form参数的值。

知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!