存储数据

大部分 Flask 应用程序会在某一时刻处理存储数据。存在许多不同的方式来存储数据。寻找最好的一种方式完全取决于你要存储的数据。如果你存储关系型数据(例如,一个用户有多篇文章,每篇文章都有一个作者等等),一个关系型数据库可能是一种合适的方式。其它类型的数据可能适合 NoSQL 数据存储,像 MongoDB。

我将不会告诉你们该如何为你的应用程序选择数据库引擎。有些人会告诉你 NoSQL 是唯一的选择,而有些人会告诉你的关系型数据是合适的选择。所有我想要说的就是如果你不确认如何选择的话,一个关系型数据库(MySQL,PostgreSQL等等)肯定能为你正在做的事情工作。

另外,当你使用一个关系型数据库的话,你就会开始使用 SQLAlchemy,SQLAlchemy 是很有趣的!

SQLAlchemy

SQLAlchemy 是一个 ORM(对象关系映射)。它基本上是在我们的数据库中执行的原始的 SQL 查询的之上的抽象层。它为一个长长的列表的数据库引擎提供一致的 API。其中最流行的数据库引擎包括 MySQL, PostgreSQL 和 SQLite。它使得在我们模型和数据库之间很容易地移动数据,并且它真的很容易地去做一些其它的事情,比如更换数据库引擎和迁移我们的数据库模式。

有一个很伟大的 Flask 扩展使得可以容易地在 Flask 中使用 SQLAlchemy。它叫做 Flask-SQLAlchemy。Flask-SQLAlchemy 为 SQLAlchemy 配置大量完整的默认值。它也处理一些会话管理因此我们不需要在我们的应用程序代码中做一些清洁工作。

让我们深入到一些代码中。我们要定义一些模型接着做一些配置工作。模型会在 myapp/models.py 中编写,但是首先需要在 myapp/init.py 中定义我们的数据库。

# ourapp/\\_\\_init\\_\\_.py

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(\\_\\_name\\_\\_, instance\\_relative\\_config=True)

app.config.from_object('config')
app.config.from_pyfile('config.py')

db = SQLAlchemy(app)

首先我们初始化以及配置我们的 Flask 应用程序,接着我们使用它来初始化我们的 SQLAlchemy 处理程序。我们将要使用一个实例文件夹来为我们的数据库配置,所以当我们初始化应用程序应该使用 instance_relative_config 选项,接着调用 app.config.from_pyfile 加载它。现在我们可以定义我们的模型。

# ourapp/models.py

from . import db

class Engine(db.Model):

    # Columns

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    title = db.Column(db.String(128))

    thrust = db.Column(db.Integer, default=0)

ColumnIntegerStringModel 以及其它的 SQLAlchemy 类可以从由 Flask-SQLAlchemy 定义的 db 对象中引用。我们已经定义了一个模型用来存储我们飞行器引擎当前的状态。每一个飞行器引擎有一个 id,一个标题以及一个推力水平。

我们还需要把一些数据库信息添加到我们配置中。我们使用一个实例文件夹为了保持敏感的配置变量不在版本控制中,所以我们将要把数据库的配置放入 instance/config.py。

# instance/config.py

SQLALCHEMY_DATABASE_URI = "postgresql://user:password@localhost/spaceshipDB"
  • 你的数据库 URI 会根据你使用的数据库引擎而不同。请参阅 SQLAlchemy 官方文档 获取更多的内容。

初始化数据库

现在数据库已经配置好了并且我们已经定义一个模型,我们可以初始化数据库。这一步基本上涉及到从模型定义中创建数据库模式。

通常这个过程可能十分痛苦。我们是幸运的,SQLAlchemy 有一个很酷的命令,它将替我们做了所有的事情。

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

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

现在多亏了 SQLAlchemy,我们的表已经在我们的配置中指定的数据库中创建好了。

Alembic 迁移数据库

数据库的模式不是一成不变的。例如,我们可能要给我们的飞行器引擎表添加一个 last_fired 字段。如果我们没有任何数据的话,我们只要更新模型和再次运行 db.create_all()。然而,如果我们已经在表中记录了 6 个月的引擎的数据,我们可能不希望从头开始。这就是数据库迁移的工作。

Alembic 是一个专门为 SQLAlchemy 使用的数据库迁移工具。它能够让我们保持我们的数据库模式的版本历史,以便我们后面可以升级到一个新的模式以及甚至退回到一个旧的版本。

Alembic 有一个很广泛的教程,大家很容易入门,因此我只给你一个简单的概述并且指出几件需要注意的事项。

我们将使用 alembic init 命令行创建我们 alembic 的“迁移环境”。一旦我们在我们的仓库/版本库中运行这个命令,我们将会有一个新的文件夹,它有一个很有创意的名字:alembic。下面这个示例改编自 Alembic 教程。

ourapp/
    alembic.ini
    alembic/
        env.py
        README
        script.py.mako
        versions/
            3512b954651e_add_account.py
            2b1ae634e5cd_add_order_id.py
            3adcc9a56557_rename_username_field.py
    myapp/
        __init__.py
        views.py
        models.py
        templates/
    run.py
    config.py
    requirements.txt

alembic/ 目录下有在不同版本之间我们数据迁移的脚本。同样也有包含配置信息的一个 alembic.ini 文件。

  • 请把 alembic.ini 添加到 .gitignore 中!你将会把你的数据库的凭证放在这个文件中,因此你 不会 要它出现在版本控制中。
  • 你想让 alembic/ 在文本控制中。它并不包含敏感信息(它不可能从你的源代码中产生的)并且保持它在版本控制中意味着有多个副本。

当开始要做出一个模式改变,会有这些步骤要走:首先我们运行 alembic revision 来生成一个迁移脚本。接着我们在 myapp/alembic/versions/ 中打开一个新生成的 Python 文件并且使用 Alembic 的 op 对象提供的工具填充 upgradedowngrade 函数。

一旦我们已经准备好我们的迁移脚本,我们可以运行 alembic upgrade head 来迁移我们的数据到最新的版本。

  • 关于配置 Alembic,创建你的迁移脚本以及运行你的迁移的细节,请参阅 Alembic 教程
  • 别忘记制定一个计划在合适的时间备份你的数据。计划的细节不在本文范围内,但是你应该一直以一种安全可靠的方式备份数据库。
  • NoSQL 场景很少在 Flask 中使用,但是只要你选择的数据库引擎有一个 Python 库,你应该能够使用它。甚至有不少 Flask 扩展 帮助整合 Flask 和 NoSQL 引擎。

摘要

  • 使用 SQLAlchemy 与关系型数据库一起工作。
  • 使用 Flask-SQLAlchemy 与 SQLAlchemy 一起工作。
  • Alembic 帮助你在数据库模式的变化之间迁移你的数据。
  • 你可以在 Flask 中使用 NoSQL,但是方法和工具与其它的数据库引擎迥异。
  • 备份你的数据!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容