二 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')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章