项目GIthub源码地址:[https://github.com/vannesspeng/TornadoForum]
留言板功能代码结构:
![](https://img.haomeiwen.com/i4038260/603cb7fe504fe712.png)
前端页面源码
style.css
.smart-green {
margin-left: auto;
margin-right: auto;
max-width: 500px;
background: #F8F8F8;
padding: 30px 30px 20px 30px;
font: 12px Arial, Helvetica, sans-serif;
color: #666;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
}
.smart-green h1 {
font: 24px "Trebuchet MS", Arial, Helvetica, sans-serif;
padding: 20px 0px 20px 40px;
display: block;
margin: -30px -30px 10px -30px;
color: #FFF;
background: #9DC45F;
text-shadow: 1px 1px 1px #949494;
border-radius: 5px 5px 0px 0px;
-webkit-border-radius: 5px 5px 0px 0px;
-moz-border-radius: 5px 5px 0px 0px;
border-bottom: 1px solid #89AF4C;
}
.smart-green h1 > span {
display: block;
font-size: 11px;
color: #FFF;
}
.smart-green label {
display: block;
margin: 0px 0px 5px;
}
.smart-green label > span {
float: left;
margin-top: 10px;
color: #5E5E5E;
}
.smart-green input[type="text"], .smart-green input[type="email"], .smart-green textarea, .smart-green select {
color: #555;
height: 30px;
line-height: 15px;
width: 100%;
padding: 0px 0px 0px 10px;
margin-top: 2px;
border: 1px solid #E5E5E5;
background: #FBFBFB;
outline: 0;
-webkit-box-shadow: inset 1px 1px 2px rgba(238, 238, 238, 0.2);
box-shadow: inset 1px 1px 2px rgba(238, 238, 238, 0.2);
font: normal 14px/14px Arial, Helvetica, sans-serif;
}
.smart-green textarea {
height: 100px;
padding-top: 10px;
}
.smart-green .button {
background-color: #9DC45F;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-border-radius: 5px;
border: none;
padding: 10px 25px 10px 25px;
color: #FFF;
text-shadow: 1px 1px 1px #949494;
}
.smart-green .button:hover {
background-color: #80A24A;
}
.error-msg{
color: red;
margin-top: 10px;
}
.success-msg{
color: #80A24A;
margin-top: 10px;
margin-bottom: 10px;
}
message.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" type="text/css" href="{{ static_url('style.css') }}">
</head>
<body>
<form action="/" method="post" class="smart-green">
<h1>留言信息
<span>请留下你的信息.</span>
</h1>
<input id="id" type="hidden" name="id" value="{{ id }}" />
<label>
<span>姓名 :</span>
<input id="name" type="text" name="name" value="{{ name }}" class="error" placeholder="请输入您的姓名"/>
<div class="error-msg"></div>
</label>
<label>
<span>邮箱 :</span>
<input id="email" type="email" value="{{ email }}" name="email" placeholder="请输入邮箱地址"/>
<div class="error-msg"></div>
</label>
<label>
<span>联系地址 :</span>
<input id="address" type="text" value="{{ address }}" name="address" placeholder="请输入联系地址"/>
<div class="error-msg"></div>
</label>
<label>
<span>留言 :</span>
<textarea id="message" name="message" placeholder="请输入你的建议">{{ message }}</textarea>
<div class="error-msg"></div>
</label>
<div class="success-msg"></div>
<label>
<span> </span>
<input type="submit" class="button" value="提交"/>
</label>
</form>
</body>
</html>
首先我们通过aiomysql_test.py来测试连接mysql数据库
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:pyy
# datetime:2018/12/27 12:37
import asyncio
from aiomysql import create_pool
async def go():
async with create_pool(host='127.0.0.1', port=3306,
user='root', password='root',
db='message', charset="utf8") as pool:
async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute("SELECT * from message")
value = await cur.fetchone()
print(value)
if __name__ == "__main__":
from tornado import ioloop
io_loop = ioloop.IOLoop.current()
io_loop.run_sync(go)
输出结果:
![](https://img.haomeiwen.com/i4038260/ab181f883ccc156a.png)
测试成功后,就是server.py的代码编写了
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:pyy
# datetime:2018/12/27 13:54
# 1. 什么是模板
import os
from tornado.web import StaticFileHandler, RedirectHandler
from aiomysql import create_pool
# 1. RedirectHandler
# 1. 301是永久重定向, 302是临时重定向,获取用户个人信息, http://www.baidu.com https
# StaticFileHandler
import time
from tornado import web
import tornado
from tornado.web import template
class MainHandler(web.RequestHandler):
# application传递过来的db参数,通过tornado框架,会自动映射到handler的initialize方法中
def initialize(self, db):
self.db = db
async def get(self, *args, **kwargs):
id = ""
name = ""
email = ""
address = ""
message = ""
# 使用协程创建mysql数据库连接池
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:
# 获取执行sql语句的cursor对象,然后执行sql语句
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
# 返回相关变量,渲染message页面
self.render("message.html", id=id, email=email, name=name, address=address, message=message)
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)
settings = {
"static_path": os.path.join(os.getcwd(), "static"),
"static_url_prefix": "/static/",
"template_path": "templates",
# 这里配置数据连接信息
"db": {
"host": "127.0.0.1",
"user": "root",
"password": "root",
"name": "message",
"port": 3306
}
}
if __name__ == "__main__":
app = web.Application([
# 数据库连接信息,通过参数传给MainHandler
("/", MainHandler, {"db": settings["db"]}),
("/static/(.*)", StaticFileHandler, {"path": os.path.join(os.getcwd(), "static")})
], debug=True, **settings)
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
提交数据到数据库,结果如下:
![](https://img.haomeiwen.com/i4038260/f98c84147296d35b.png)
留言板功能目录结构和源码,已全部提供,大家可以自行尝试,通过调试来理解程序执行流程。
网友评论