二 Flask Project 实战 一

1 Project Layout

规划project layout
1 Project目录: 作为project的根目录,组织application
2 Project下的子目录:
2.1 <application> 包含code和文件的python package,其下有init.py
2.2 <tests> 包含tests模块的目录
2.3 <venv> 安装flask和其他依赖的virtual environment
3 setup.py 指导如何安装project

2 Application Setup

概念
application factory: 在一个函数中完成Flask实例的创建,配置。
configuration and URLs, will be registered with this class Flask

init.py有两个duty: 一个是指明application目录是一个Python package,另外一个就是创建Application factory 函数。

案例
def create_app(test_config=None):
#create and configure the app
#name指明app的path,用来setup 其它路径
#instance_relative_config指明app的configuration文件对应到instance目录
app = Flask(name,instance_relative_config=True)
#设置app默认的配置
app.config.from_mapping(
#加密数据
SECRET_KEY='dev',
#指明数据库的path
DATABASE=os.path.join(app.instance_path,'flaskr.sqlite'),
)

if test_config is None:
            #从config.py中获取配置,override默认的configuration
    app.config.from_pyfile('config.py',silent=True)
else:
    app.config.from_mapping(test_config)

try:
    os.makedirs(app.instance_path)
except OSError:
    pass

@app.route('/')
def hello():
    return 'Hello'

return app

运行
export FLASK_APP=flaskr #package name
export FLASK_ENV=development
flask run

note:
默认的application factory 的名字是create_app,如果修改需要指定FLASK_APP=flaskr:create_app

3 Define and Access the Database

3.1 Connect to the Database

#该connection与每一个request是bind的,其在处理request时被创建,在返回response前被关闭。
#g对每一个request来说,是唯一的。在请求中,用来存储被多个函数访问的对象。
#sqlite3.Row告诉创建的connection, 返回的数据像数据字典
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row

3.2 Create the Tables

#使用
def init_db():
db = get_db()
#根据package路径,打开一个file。这样就不用考虑path问题了
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))

#定义了a command line 叫init-db
#使用flask init-db 命令来初始化DBbr/>@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.')

3.3 Register with the Application

init db和close db应该在Application instance中注册
def init_app(app):
#在返回response时,告诉APP调用close_db来清理
app.teardown_appcontext(close_db)
#添加一个new command,可以通过flask 来调用
app.cli.add_command(init_db_command)

#在factor中调用以下code
from . import db
db.init_app(app)

4 Blueprints and Views

概念:
Blueprint:一种组织view和code的组方式,而不是直接在Application张注册view和code 。
view and code 在Blueprint中 register,Blueprint在Application中注册。

4.1 Create a Blueprint

#创建一个名为auth,使用name来指定创建位置,
url_prefix说明所有与blueprint相关的URL前缀为/auth
bp = Blueprint('auth', name, url_prefix='/auth')

在factory中import和register blueprint
from . import auth
app.register_blueprint(auth.bp)

4.2 The First View: Register

URL: /auth/register

#使用blueprint来指明URL路由,当请求/auth/retister时,call 视图register
@bp.route('/register', methods=('GET', 'POST'))
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
db = get_db()
error = None

    if not username:
        error = 'Username is required.'
    elif not password:
        error = 'Password is required.'
    elif db.execute(
        'SELECT id FROM user WHERE username = ?', (username,)
    ).fetchone() is not None:
        error = 'User {} is already registered.'.format(username)

    if error is None:
                    #函数generate_password_hash生成password的hash值
        db.execute(
            'INSERT INTO user (username, password) VALUES (?, ?)',
            (username, generate_password_hash(password))
        )
        db.commit()
        return redirect(url_for('auth.login'))

            #存储信息,可以被template来使用
    flash(error)

return render_template('auth/register.html')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章