在前面章節描述的數據庫操做是能夠在視圖函數中直接使用的。示例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
每次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-SQLAlchemy只有當數據庫表不存在了才從模型建立它們,因此更新表的惟一途徑就是銷燬舊的表,固然這將致使全部數據庫中的數據丟失。
有個更好的解決方案就是使用數據庫遷移框架。和源碼版本控制工具跟蹤更改源碼文件同樣,數據庫遷移框架跟蹤更改數據庫模型,而後將增量變化應用到數據庫中。
SQLAlchemy的主要開發人員寫了一個Alembic遷移框架,但咱們不直接使用Alembic,Flask應用可使用Flask-Migrate擴展,一個集成了Flask-Script來提供全部操做命令的輕量級Alembic包。
首先,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
來切換到這個版本的應用程序。
在Alembic,數據庫遷移工做由遷移腳本完成。這個腳本有兩個函數,分別叫作upgrade()
和downgrade()
。upgrade()
函數實施數據庫更改,是遷移的一部分,downgrade()
函數則刪除它們。經過添加和刪除數據庫變化的能力,Alembic能夠從新配置數據庫從歷史記錄中的任什麼時候間點。
Alembic遷移能夠分別使用revision
和migrate
命令手動或自動建立。手動遷移經過由開發人員使用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,全部的遷移腳本都包含在版本庫中。
一旦遷移腳本被審查且接受,就可使用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
命令對錶實施更新操做但不影響表中的內容。
數據庫的設計和使用是很是重要的,事實上整本書都是圍繞這個主題來寫的。你應該把本章做爲一個概述來研究;更高級的主題將在之後的章節中討論。下一章致力於講解發送電子郵件。