存储

存储

大多数 Flask 应用都将要跟数据打交道。有很多种不同的方法存储数据。至于哪种最优,取决于数据的类型。如果你储存的是关系性数据(比如一个用户有多个邮件,一个邮件对应一个用户),关系型数据库无疑是你的选择。其他类型的数据也许适合储存到 NoSQL 数据库(比如 MongoDB)中。

我不会告诉你如何为你的应用选择数据库。如果有人告诉你,NoSQL 是你的唯一选择;那么必然也会有人建议用关系型数据库处理同样的问题。对此我唯一需要说的是,如果你不清楚,关系型数据库(MySQL, PostgreSQL 等等)将满足你绝大部分的需求。

另外,当你使用关系型数据库,你就能用到 SQLAlchemy,而 SQLAlchemy 用起来真爽。

SQLAlchemy

SQLAlchemy 是一个 ORM(对象关系映射)。基于对目标数据库的原生 SQL 的抽象,它提供了与一长串数据库引擎的一致的 API。这一列表中包括 MySQL,PostgreSQL,和 SQLite。这使得在你的模型和数据库间交换数据变得轻松愉快,同时也使得诸如换掉数据库引擎和迁移数据库模式等其他事情变得没那么繁琐。

存在一个很棒的 Flask 插件使得在 Flask 中使用 SQLAlchemy 更为轻松。它就是 Flask-SQLAlchemy。Flask-SQLAlchemy 为 SQLAlchemy 设置了许多合理的配置。它也内置了一些 session 管理,这样你就不用在应用代码里处理这种基础事务了。

让我们深入看看一些代码。我们将先定义一些模型,接着配置下 SQLAchemy。这些模型将位于 myapp/models.py,不过首先我们要在 myapp/__init__.py 定义我们的数据库。

myapp/__init__.py_

  1. from flask import Flask
  2. from flask_sqlalchemy import SQLAlchemy
  3. app = Flask(__name__, instance_relative_config=True)
  4. app.config.from_object('config')
  5. app.config.from_pyfile('config.py')
  6. db = SQLAlchemy(app)

我们首先初始化并配置你的 Flask 应用,然后用它来初始化你的 SQLAlchemy 数据库处理程序。我们将为数据库配置使用一个 instance 文件夹,所以我们应该在初始化应用时加上 instance_relative_config 选项,然后调用 app.config.from_pyfile。现在我们可以定义模型了。

myapp/models.py

  1. from . import db
  2. class Engine(db.Model):
  3. # Columns
  4. id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  5. title = db.Column(db.String(128))
  6. thrust = db.Column(db.Integer, default=0)

ColumnIntegerStringModel 和其他的 SQLAlchemy 类都可以通过由 Flask-SQLAlchemy 构造的 db 对象访问。我们会定义一个储存我们的太空飞船引擎的当前状态的模型。每个引擎有一个 ID,一个标题和一个推力等级。

我们需要往我们的配置添加一些数据库信息。我们打算使用一个 instance 文件夹来避免配置变量被记录进版本控制系统,所以我们要把它们放入 instance/config.py

instance/config.py

  1. SQLALCHEMY_DATABASE_URI = "postgresql://user:password@localhost/spaceshipDB"

注意 你的数据库URI将取决于你选择的数据库和它部署的位置。看一下这个相关的SQLAlchemy文档: http://docs.sqlalchemy.org/en/latest/core/engines.html?highlight=database#database-urls

初始化数据库

既然数据库已经配置好了,而模型也定义了,是时候初始化数据库了。这个步骤从由模型定义中创建数据库模式开始。

通常这会是非常痛苦的过程。不过幸运的是,SQLAlchemy 提供了一个十分酷的工具帮我们完成了所有的琐事。

让我们在版本库的根目录下打开一个 Python 终端。

  1. $ pwd
  2. /Users/me/Code/myapp
  3. $ workon myapp
  4. (myapp)$ python
  5. Python 2.7.5 (default, Aug 25 2013, 00:04:04)
  6. [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
  7. Type "help", "copyright", "credits" or "license" for more information.
  8. >>> from myapp import db
  9. >>> db.create_all()
  10. >>>

现在,感谢 SQLAlchemy,你会发现在你配置的数据库中,所需的表格已经被创建出来了。

Alembic 迁移工具

数据库的模式并非亘古不变的。举个例子,你可能需要在引擎的表里添加一个 last_fired 的项。如果这个表是一张白纸,你只需要更新模型并重新运行 db.create_all()。然而,如果你在引擎表里记录了六个月的数据,你肯定不会想要从头开始。这时候就需要数据库迁移工具了。

Alembic 是专用于 SQLAlchemy 的数据库迁移工具。它允许你保持你的数据库模式的版本历史,这样你就可以升级到一个新的模式,或者降级到旧的模式。

Alembic 有一个可拓展的新手教程,所以我只会大概地说一下并指出一些需要注意的事项。

通过一个初始化的 alembic init 命令,你将创建一个 alembic “迁移环境”。在你的版本库的根目录下执行这个命令,你将得到一个叫 alembic 的新文件夹。你的版本库将看上去就像 Alembic 教程中的这个例子一样:

  1. myapp/
  2. alembic.ini
  3. alembic/
  4. env.py
  5. README
  6. script.py.mako
  7. versions/
  8. 3512b954651e_add_account.py
  9. 2b1ae634e5cd_add_order_id.py
  10. 3adcc9a56557_rename_username_field.py
  11. myapp/
  12. __init__.py
  13. views.py
  14. models.py
  15. templates/
  16. run.py
  17. config.py
  18. requirements.txt

alembic/ 文件夹中包括了在版本间迁移数据的脚本。同时会有一个包括配置信息的 alembic.ini 文件。

注意alembic.ini添加到.gitignore中!在那里会有你的数据库凭证,所以你不应该把它留在版本控制中。

不过你可以把alembic/放进版本控制。它不会包含敏感信息(而且不能从你的源代码中重新生成),并且在版本控制中保存多个副本可以避免你的电脑发生不测。

当数据库模式需要发生变化时,我们需要做一系列事情。首先,运行 alembic revision 来生成迁移脚本。在 myapp/alembic/versions/ 打开新生成的 Python 文件并使用 Alembic 的 op 对象完成 upgradedowngrade 函数。

一旦我们的迁移脚本已经准备就绪,我们只需运行 alembic upgrade head 来迁移我们的数据到最新版本。

参见 想知道更多关于配置Alembic,创建你的迁移脚本和运行你的迁移,请看Alembic教程: http://alembic.readthedocs.org/en/latest/tutorial.html

注意 不要忘记设定数据的备份计划。备份计划的话题已经超出本书的范围,但你应该总是要有一个安全和健壮的方式备份你的数据库。

注意 Flask在NoSQL上的支持较少,但只要有你选择的数据库引擎有对应的Python库,你就能够用上它。这里有一些Flask插件,可以给Flask提供NoSQL引擎的支持。 http://flask.pocoo.org/extensions/

总结

  • 使用 SQLAchemy 来搭配关系型数据库。
  • 使用 Flask-SQLAlchemy 来包装 SQLAlchemy。
  • Alembic 会在数据库模式改变时帮助你管理数据迁移。
  • 你可以用 NoSQL 搭配 Flask,但具体做法取决于具体引擎。
  • 记得备份你的数据!