Flask Web Development —— 數據庫(下)

九、數據庫在視圖函數中的使用

在前面章節描述的數據庫操做是能夠在視圖函數中直接使用的。示例5-5展現的新版本主頁實現了用戶輸入名字並保存到數據庫中。html

示例5-5. hello.py:數據庫在視圖函數中的使用python

@app.route('/', methods=['GET', 'POST']) 
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first() 
        if user is None:
            user = User(username = form.name.data)
            db.session.add(user)
            session['known'] = False
        else:
            session['known'] = True
        session['name'] = form.name.data 
        form.name.data = ''
        return redirect(url_for('index'))
    return render_template('index.html',
        form = form, name = session.get('name'), known = session.get('known', False))

在這個已修改的應用程序版本中,每次提交一個名字應用程序都要使用filter_by()查詢過濾器到數據庫中檢查一遍。known變量被寫入到用戶會話中,這樣在重定向後信息就能夠發送到模板來定製問候語。注意爲了應用程序能夠工做,必須建立好以前在Python shell中展現的那些數據庫表。git

新版本的相關模板在示例5-6中展現。這個模板使用known參數用於區分是已知用戶仍是新用戶的問候。sql

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky{% endblock %}

{% block page_content %}


<div class="page-header">
  <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1> 
  {% if not known %}
  <p>Pleased to meet you!</p>
  {% else %}
  <p>Happy to see you again!</p>
  {% endif %}
</div>


{{ wtf.quick_form(form) }}
{% endblock %}

建議:若是你有克隆在GitHub上的應用程序,你如今能夠運行git checkout 5b來切換到這個版本的應用程序。shell

十、與python shell的集成

每次shell會話啓動都必須導入數據庫實例和模型是很是單調乏味的工做。爲了不不斷重複這些導入,能夠配置Flask-Script的shell命令來自動導入特定的對象。數據庫

shell命令須要註冊make_context回調函數來將對象添加到導入列表。如示例5-7所示。flask

示例5-7. hello.py:增長shell上下文bootstrap

from flask.ext.script import Shell 

def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)
manager.add_command("shell", Shell(make_context=make_shell_context))

make_shell_context()函數註冊應用程序和數據庫的實例及模型,這樣就能夠自動導入到shell中了:session

$ python hello.py shell
>>> app
<Flask 'app'>
>>> db
<SQLAlchemy engine='sqlite:////home/flask/flasky/data.sqlite'> 
>>> User
<class 'app.User'>

建議:若是你有克隆在GitHub上的應用程序,你如今能夠運行git checkout 5c來切換到這個版本的應用程序。app

十一、使用Flask-Migrate遷移數據庫

隨着開發進度不斷向前,你會發現你的數據庫模型須要更改,而當這種狀況發生時須要更新數據庫。

Flask-SQLAlchemy只有當數據庫表不存在了才從模型建立它們,因此更新表的惟一途徑就是銷燬舊的表,固然這將致使全部數據庫中的數據丟失。

有個更好的解決方案就是使用數據庫遷移框架。和源碼版本控制工具跟蹤更改源碼文件同樣,數據庫遷移框架跟蹤更改數據庫模型,而後將增量變化應用到數據庫中。

SQLAlchemy的主要開發人員寫了一個Alembic遷移框架,但咱們不直接使用Alembic,Flask應用可使用Flask-Migrate擴展,一個集成了Flask-Script來提供全部操做命令的輕量級Alembic包。

11.一、建立遷移倉庫

首先,Flask-Migrate必須已經安裝到虛擬環境中:

(venv) $ pip install flask-migrate

示例5-8展現擴展如何初始化。

示例5-8. hello.py:Flask-Migrate配置

from flask.ext.migrate import Migrate, MigrateCommand 

# ...

migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)

爲了可使用數據庫遷移命令,Flask-Migrate提供MigrateCommand類來鏈接Flask-Script的manager對象。在這個示例中使用db來鏈接到命令。

在數據庫遷移能夠維護以前,必須經過init子命令來建立一個遷移庫:

(venv) $ python hello.py db init
  Creating directory /home/flask/flasky/migrations...done
  Creating directory /home/flask/flasky/migrations/versions...done
  Generating /home/flask/flasky/migrations/alembic.ini...done
  Generating /home/flask/flasky/migrations/env.py...done
  Generating /home/flask/flasky/migrations/env.pyc...done
  Generating /home/flask/flasky/migrations/README...done
  Generating /home/flask/flasky/migrations/script.py.mako...done
  Please edit configuration/connection/logging settings in
  '/home/flask/flasky/migrations/alembic.ini' before proceeding.

這個命令建立一個migrations文件夾,裏面存放了全部遷移腳本。

建議:若是你有克隆在GitHub上的應用程序,你如今能夠運行git checkout 5c來切換到這個版本的應用程序。

11.二、建立遷移腳本

在Alembic,數據庫遷移工做由遷移腳本完成。這個腳本有兩個函數,分別叫作upgrade()downgrade()upgrade()函數實施數據庫更改,是遷移的一部分,downgrade()函數則刪除它們。經過添加和刪除數據庫變化的能力,Alembic能夠從新配置數據庫從歷史記錄中的任什麼時候間點。

Alembic遷移能夠分別使用revisionmigrate命令手動或自動建立。手動遷移經過由開發人員使用Alembic的Operations對象指令實現的空upgrade()downgrade()函數建立遷移框架腳本。另外一方面,自動遷移經過尋找模型定義和數據庫當前狀態間的不一樣爲upgrade()downgrade()生成代碼。

警告:自動遷移並不老是準確的,能夠忽略一些細節。因此應該常常審查一下自動生成的遷移腳本。

migrate子命令建立自動遷移腳本:

(venv) $ python hello.py db migrate -m "initial migration"
INFO  [alembic.migration] Context impl SQLiteImpl.
INFO  [alembic.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate] Detected added table 'roles'
INFO  [alembic.autogenerate] Detected added table 'users'
INFO  [alembic.autogenerate.compare] Detected added index
'ix_users_username' on '['username']'
  Generating /home/flask/flasky/migrations/versions/1bc
  594146bb5_initial_migration.py...done

建議:若是你有克隆在GitHub上的應用程序,你如今能夠運行git checkout 5c來切換到這個版本的應用程序。注意,你不須要爲這個應用生成migrations,全部的遷移腳本都包含在版本庫中。

11.三、更新數據庫

一旦遷移腳本被審查且接受,就可使用db upgrade命令更新到數據庫中:

(venv) $ python hello.py db upgrade
INFO  [alembic.migration] Context impl SQLiteImpl.
INFO  [alembic.migration] Will assume non-transactional DDL.
INFO  [alembic.migration] Running upgrade None -> 1bc594146bb5, initial migration

第一次遷移實際上至關於調用db.create_all(),但在後續遷移中,upgrade命令對錶實施更新操做但不影響表中的內容。

數據庫的設計和使用是很是重要的,事實上整本書都是圍繞這個主題來寫的。你應該把本章做爲一個概述來研究;更高級的主題將在之後的章節中討論。下一章致力於講解發送電子郵件。

相關文章
相關標籤/搜索