平时做数据分析挖掘的结果,难免会需要在Web上展示出来,这样更有逼格。那么,开发web页面难吗?使用Java开发门槛太高,一堆注解绝对让你投降;使用PHP开发,好像太骚了。其实,我们需要有这么一个工具,既能做数据分析挖掘,又能做web展示,非你莫属了——Python。
这里,选择Python的轻量级框架Flask,开发速度更快,开发一个简单的话题发布,支持基本的登陆、注销功能。
未登录前,可以浏览,登陆后可以发布话题,注销后可以浏览。
未登陆前
位登陆前,支持浏览,只读权限,右上角有登陆按钮。
登陆后
登陆后,可以发布主题,可以注销。
可以看到,功能非常简单,这是第一步,有了基础才能自己学习,做出炫酷的分析结果。
项目过程,分为以下几步:
web服务的第一个请求之前,需要初始化数据库连接;
游客(未登陆状态),可以看到所有话题;
为了简化,只有一个用户硬编码,没有用户表;
登陆之后,可以发布主题,数据保存到数据库;
注销后,回到游客状态;
这个项目是flask官方入门项目,取名flaskr,工程目录结构如下:
flask目录:这里暂且记为项目根目录;
static:存放网站静态文件,包括css样式,图片文件等;
templates:前端jinja2 html模板文件;
entries.db:SQLite3数据文件;
flaskr.py:Python项目主要代码文件;
schema.sql:建表文件,这里需要一张表,保存用户发布的话题;
最后,会上完整代码,复制过去可以直接运行的。
初始化上下文环境
首先初始化应用和一些变量,包括Flask实例,g对象,如果使用session,需要初始化一个app.secret_key
import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash
app = Flask(__name__, instance_path='D:/我的文件/Codes/PyCode/web/flask/flaskr')
app.config['USERNAME'] = 'name'
app.config['PASSWORD'] = 'password'
app.secret_key = 'ajflafoo8qm.mgaj'
# DATABASE = 'D:/我的文件/Codes/PyCode/web/flask/flaskr/entries.db'
DATABASE = os.path.join(os.getcwd(), 'entries.db')
注意:自己电脑上面执行的时候,D:/我的文件/Codes/PyCode/web/flask/flaskr,这个是我的SQLite3地址,需要换成自己的,对应地址。
初始化数据库
由于是"Hello world"入门项目,这里使用的数据库是小型的磁盘型数据库SQLite3,没必要连接大型数据库。
SQLite3何许人也?
SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。
连接数据库,需要获取数据库连接,SQLite3数据库不错在,则会新建一个文件夹,名字为数据库名:
def get_db():
"""connect to special database"""
return sqlite3.connect(DATABASE)
第一次运行需要初始化数据库和表,调用init_table方法即可。
def init_table():
"""first run create table"""
db = get_db()
result = db.cursor().execute(
"SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = 'entries'").fetchall()
table_exists = result[0][0] == 1
# 不存在,则创建表
if not table_exists:
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
else:
print('entries already exists .')
db.close()
每一个请求之前@app.before_request需要连接数据库,request请求之后@app.teardown_request关闭数据库:
@app.before_request
def before_request():
g.db = get_db()
@app.teardown_request
def teardown_request(exception):
if hasattr(g, 'db'):
g.db.close()
通常,用户登陆后,才有权限发表话题,注销后就是游客身份,只能看,不能发布话题。
显示所有发布的话题
@app.route('/')
def show_entries():
"""显示条目"""
sql = 'select title, text from entries order by id desc'
cursor = g.db.cursor()
entries = [dict(title = row[0], text = row[1]) for row in cursor.execute(sql).fetchall()]
cursor.close()
return render_template('show_entries.html', entries = entries)
用户登陆
为了简单起见,没有建用户表,只是在内存中定义了一个用户,用户名:name,密码:password。
@app.route('/login', methods=['GET', 'POST'])
def login():
"""登陆函数"""
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
return render_template('login.html', error = error)
用户注销
注销后,直接重定向到主页。
@app.route('/logout')
def logout():
"""注销函数"""
session.pop('logged_in', None)
flash('You were logged out')
return redirect(url_for('show_entries'))
用户登陆后,可以发布话题,内容存在SQLite3数据库里面,用户每次刷新或者跳转到主页需要读取数据库,显示。通过表单发送数据,methods是POST。
@app.route('/add', methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
sql = 'insert into entries(title, text) values(?, ?)'
g.db.execute(sql, [request.form['title'], request.form['text']])
g.db.commit()
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
完整代码,这里还是贴出来吧,虽然不太美观,确保Python3已经安装了flask模块,否则通过pip3 install flask命令即可安装 ,代码可以直接执行。
这里是主要逻辑代码flaskr.py。
import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash
app = Flask(__name__, instance_path='D:/我的文件/Codes/PyCode/web/flask/flaskr')
app.config['USERNAME'] = 'name'
app.config['PASSWORD'] = 'password'
app.secret_key = 'ajflafoo8qm.mgaj'
# DATABASE = 'D:/我的文件/Codes/PyCode/web/flask/flaskr/entries.db'
DATABASE = os.path.join(os.getcwd(), 'entries.db')
def init_table():
"""first run create table"""
db = get_db()
result = db.cursor().execute(
"SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = 'entries'").fetchall()
table_exists = result[0][0] == 1
# 不存在,则创建表
if not table_exists:
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
else:
print('entries already exists .')
db.close()
def get_db():
"""connect to special database"""
return sqlite3.connect(DATABASE)
"""
@app.before_request
def get_connection():
db = getattr(g, 'db', None)
if db is None:
db = g.db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
"""
@app.before_request
def before_request():
g.db = get_db()
@app.teardown_request
def teardown_request(exception):
if hasattr(g, 'db'):
g.db.close()
@app.route('/')
def show_entries():
"""显示条目"""
sql = 'select title, text from entries order by id desc'
cursor = g.db.cursor()
entries = [dict(title = row[0], text = row[1]) for row in cursor.execute(sql).fetchall()]
cursor.close()
return render_template('show_entries.html', entries = entries)
@app.route('/add', methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
sql = 'insert into entries(title, text) values(?, ?)'
g.db.execute(sql, [request.form['title'], request.form['text']])
g.db.commit()
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
@app.route('/login', methods=['GET', 'POST'])
def login():
"""登陆函数"""
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
return render_template('login.html', error = error)
@app.route('/logout')
def logout():
"""注销函数"""
session.pop('logged_in', None)
flash('You were logged out')
return redirect(url_for('show_entries'))
if __name__ == '__main__':
# 第一次执行,需要初始化数据库,和表
init_table()
app.run(debug=True)
还有前端代码,就不贴出来了,完整项目已经上传到Github,https://github.com/ddxygq/PyCode/tree/master/web/flask/flaskr
Github代码下载下来,可以直接执行的。