定义并访问数据库
该应用程序将使用 SQLite 数据库来存储用户和帖子。Python 在 sqlite3 模块中内置了对 SQLite 的支持。
SQLite 很方便使用,因为它不需要设置单独的数据库服务器,并且内置于 Python 中。但是,如果并发请求试图同时向数据库写入数据,则每次写入都会按顺序进行,因此速度会减慢。小型应用程序不会在意这点。一旦程序变大了,可能就想要切换到另一个数据库。
本教程没有详细介绍 SQL。如果你不熟悉,请参阅 SQLite 官方文档。
连接到数据库
使用 SQLite 数据库(以及大多数其他 Python 数据库)时要做的第一件事是创建到它的连接。任何查询和操作都通过连接执行,该连接在工作完成后关闭。
在 web 应用程序中,这种连接通常与请求相关联。它在处理请求时的某个时间点创建,并在发送响应之前关闭。
# flaskr/db.pyimport sqlite3import clickfrom flask import current_app, gfrom flask.cli import with_appcontextdef get_db():if 'db' not in g:g.db = sqlite3.connect(current_app.config['DATABASE'],detect_types=sqlite3.PARSE_DECLTYPES)g.db.row_factory = sqlite3.Rowreturn g.dbdef close_db(e=None):db = g.pop('db', None)if db is not None:db.close()
g 是一个特殊的对象,对于每个请求都是唯一的。它用于存储请求期间多个函数可能访问的数据。该连接会被存储,如果在同一请求中第二次调用 get_db,则会重用连接,而不是创建新连接。
current_app 是另一个特殊对象,指向处理请求的 Flask 应用程序。由于使用了应用程序工厂,所以在编写其余代码时没有应用程序对象。get_db 将在创建应用程序并处理请求时调用,因此可以使用 current_app。
sqlite3.connect() 与 DATABASE 配置键指向的文件建立连接。这个文件此时还不存在,直到稍后初始化数据库。
sqlite3.Row 告诉连接返回行数据,类似于使用字典,可以按名称访问列。
close_db 通过 g.db 来检查是否创建了连接。如果连接存在,它将关闭。接下来,在应用程序工厂中引入 close_db 函数,以便在每次请求后调用它。
创建表
在 SQLite 中,数据存储在表和列中。在存储和检索数据之前,需要先创建这些表和列。Flaskr 将用户存储在 user 表中,并将帖子存储在 post 表中。创建一个带有 SQL 命令的文件,这些命令用于创建空表:
flaskr/schema.sql
DROP TABLE IF EXISTS user;DROP TABLE IF EXISTS post;CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT UNIQUE NOT NULL,password TEXT NOT NULL);CREATE TABLE post (id INTEGER PRIMARY KEY AUTOINCREMENT,author_id INTEGER NOT NULL,created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,title TEXT NOT NULL,body TEXT NOT NULL,FOREIGN KEY (author_id) REFERENCES user (id));
向 db.py 文件添加 Python 函数,运行这些 SQL 命令:
# flaskr/db.pydef init_db():db = get_db()with current_app.open_resource('schema.sql') as f:db.executescript(f.read().decode('utf8'))@click.command('init-db')@with_appcontextdef init_db_command():"""Clear the existing data and create new tables."""init_db()click.echo('Initialized the database.')
open_resource() 打开一个文件,文件路径相对于 flaskr 软件包,这很有用,因为在以后部署应用程序时,不一定知道该位置在哪里。get_db 返回一个数据库连接,用于执行从文件读取的命令。
click.command() 定义一个名为 init-db 的命令行命令,该命令调用 init_db 函数,并向用户显示一条成功消息。
注册应用程序
close_db 和 init_db_command 函数需要在应用程序实例中注册;否则,应用程序将不会使用它们。但是,由于使用的是工厂函数,因此在编写函数时该实例不可用。可以编写一个函数来接受应用程序并进行注册。
# flaskr/db.pydef init_app(app):app.teardown_appcontext(close_db)app.cli.add_command(init_db_command)
app.teardown_appcontext() 告诉 Flask 在返回响应后进行清理时调用该函数。
app.cli.add_command() 添加一个可以用 flask 命令调用的新命令。
从工厂导入并调用此函数。将新代码放在出厂函数的末尾,在返回应用程序之前。
# flaskr/__init__.pydef create_app():app = ...# existing code omittedfrom . import dbdb.init_app(app)return app
初始化数据库文件
现在 init-db 已经在应用程序中注册,可以使用 flask 命令调用它,类似于之前的 run 命令。
运行 init-db 命令:
>flask init-db
现在项目中 instance 文件夹中将有一个 flaskr.sqlite 文件。
原文:
https://flask.palletsprojects.com/en/2.0.x/tutorial/database/




