flask的安装请参见这个
项目的布局
整个教程都是在flask_tutorial这个目录下进行的。
依照系列一中的内容,先创建一个简单的文件hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
但是随着项目的增大,不可能将所有的代码放在一个文件中。所以需要根据不同代码文件的功能将其分为不同的模块,在这里项目将会被分为这样的几个模块:
应用安装
flask的应用实际上是一个flask类的实例,关于这个应用的任何东西,包括配置文件和url,都将会在这个类里面注册。
创建一个flask应用最为直接的方法就是创建一个flask全局实例,但是随着项目的增大这种方法会带来很多的麻烦。
这里我们并不会创建一个flask全局的实例,而是要在一个函数中创建。这个函数便是应用工厂函数,一切的配置,注册,以及应用所需要的设置都会包含在这个文件中,最后这个应用将会被返回。
应用工厂函数
接下来我们将创建应用工厂函数,这个函数将有两个功能,第一它会包含应用工厂;第二它会告诉pythonflaskr目录应该被视为一个包。
flaskr/init.py
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
@app.route('/hello')
def hello():
return 'Hello, World!'
return app
运行应用
在终端中的flaskr当前路径下运行以下代码(window版,其他版本参见)
set FLASK_APP=flaskr
set FLASK_ENV=development
flask run
输出这个样:
* Serving Flask app "flaskr"
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 855-212-761
这时便可以访问http://127.0.0.1:5000/hello来查看结果。
定义和访问数据库
本次的应用将会采用SQLite数据库存储用户信息,python中在sqlite3中有内置的支持。
SQLite非常方便,原因在于其不需要设置一个一个隔离的数据库服务器,但是如果在同一时间有并发的请求写入数据库的话,写入放入速率就会降低。这一点会在大的项目中出现。
连接数据库
数据库的任何操作都是在连接好的基础上实现的。在web应用中,数据库连接多数发生请求到来时,在处理请求的某一个时间点连接会被创建,响应被发送后连接会被关闭。
flaskr/db.py
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
我们在系列一种稍微提到过g对象。g对象对于每一个请求来说都是独一无二的,它的主要功能是存储数据,这些数据可能会在请求的过程中会被用到。如果get_db在同一个请求中被第二次调用的话,连接会被重用而非重新建立一个连接。
上面代码中:
创建表
SQLite中,数据是被存储在表和列中的,这些在你存储和检索数据之前就需要被创建, Flaskr将会在user表中存储user,在post表中存储评论的信息。创建Sql文件的命令:
flaskr/schema.sql
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
body TEXT NOT NULL,
FOREIGN KEY (author_id) REFERENCES user (id)
);
下面的函数将会返回sql命令给db.py
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
@click.command('init-db')
@with_appcontext
def init_db_command():
"""Clear the existing data and create new tables."""
init_db()
click.echo('Initialized the database.')
上面代码中:
注册该应用
close_db和init_db_command函数都需要一个应用实例,但是我们所使用的是工厂函数,在写这个工厂函数时实例是不可以用的。因此,必须要写一个能够获取一个实例并注册应用的函数。
flaskr/db.py
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
从工厂中导入和调用这个函数。
flaskr/init.py
ef create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
初始化数据库文件
现在init_db命令已经在应用中注册过,使用flask的命令便可以调用它。
如果你仍在之前的页面运行该服务,你最好重新再一个新的终端中运行它
运行init_db的命令
flask init-db
Initialized the database.
现在在你的项目布局中应该会有flaskr.sqlite文件出现。
好了,系列二就到这里,本次主要讲了工厂函数的创建以及数据库连接的建立。
如有错误请多指正!