Flask教程-Flask操作数据库
在这个教程中,我们选择了SQLite作为数据库管理系统(DBMS)。SQLite是一种关系型数据库管理系统(RDBMS),它基于文件,不需要单独启动数据库服务器。SQLite适合在开发时使用,或者在数据库操作简单、访问量低的程序中使用。
SQLite具有以下优点:
- 简单易用:SQLite的设置和配置非常简单,无需复杂的服务器安装和配置过程。
- 轻量级:SQLite数据库以单个文件的形式存储在磁盘上,占用空间小且资源消耗较少。
- 无服务器:与其他关系型数据库管理系统相比,SQLite不需要独立运行的数据库服务器,可以直接与应用程序集成。
- 跨平台:SQLite可在多个操作系统上运行,包括Windows、Mac和Linux等。
需要注意的是,SQLite适用于小型应用程序或原型开发,如果您的应用程序需要处理大量数据或高并发访问,可能需要考虑更高级的数据库管理系统,如MySQL或PostgreSQL。
在接下来的教程中,我们将使用Flask-SQLAlchemy扩展与SQLite数据库进行交互,以简化数据库操作过程。
使用SQLAlchemy操作数据库
为了简化数据库操作,我们将使用SQLAlchemy,它是一个Python数据库工具(ORM,即对象关系映射)。借助SQLAlchemy,您可以通过定义Python类来表示数据库中的表(类属性表示表中的字段/列),通过对这个类进行各种操作来代替编写SQL语句。我们将这个类称为模型类,其中的属性被称为字段。
Flask有许多第三方扩展,这些扩展可以简化与第三方库的集成。下面我们将使用一个名为Flask-SQLAlchemy的扩展来集成SQLAlchemy。
首先安装它:
(env) $ pip install flask-sqlalchemy==2.5.1 sqlalchemy==1.4.47
提示:Flask-SQLAlchemy 3.x / SQLAlchemy 2.x 版本有一些重大变化。在此处,我们固定安装了2.5.1和1.4.47版本。在更新的教程中,将删除这里的版本限制。
大多数扩展都需要执行一个"初始化"操作。您需要导入扩展类,实例化它并传入Flask应用程序实例:
from flask_sqlalchemy import SQLAlchemy # 导入扩展类
app = Flask(__name__)
db = SQLAlchemy(app) # 初始化扩展,传入Flask应用程序实例 app
现在,您已经成功初始化了Flask-SQLAlchemy扩展。
使用模型类定义数据库表
在Python Shell中执行以下代码:
(env) $ flask shell
>>> from app import db
>>> db.create_all()
这将创建一个名为data.db
的SQLite数据库文件,并根据模型类创建对应的表。你可以在文件管理器中查看到这个数据库文件。请注意,数据库文件不应该提交到版本控制系统中,因此我们在.gitignore
文件中添加了对应的规则。
如果你对模型类进行了更改,需要重新生成表结构,可以使用以下代码:
>>> db.drop_all()
>>> db.create_all()
这会删除所有的表并重新创建。但请注意,这将清空所有数据。如果你需要在保留数据的情况下修改表结构,你可以使用数据库迁移工具,如Flask-Migrate扩展。
为了方便使用,我们还创建了一个自定义命令initdb
,可以通过命令行初始化数据库:
import click
@app.cli.command()
@click.option('--drop', is_flag=True, help='Create after drop.')
def initdb(drop):
"""Initialize the database."""
if drop:
db.drop_all()
db.create_all()
click.echo('Initialized database.')
你可以使用以下命令初始化数据库:
(env) $ flask initdb
如果你想先删除表再重新创建,可以使用--drop
选项:
(env) $ flask initdb --drop
以上是创建数据库模型的步骤。
数据库增删改查
接下来我们将学习如何使用数据库模型类进行数据库操作,包括创建、读取、更新和删除记录。
创建记录:
from app import User, Movie
user = User(name='Grey Li')
m1 = Movie(title='Leon', year='1994')
m2 = Movie(title='Mahjong', year='1996')
db.session.add(user)
db.session.add(m1)
db.session.add(m2)
db.session.commit()
以上代码演示了如何创建User
和Movie
的记录,并使用db.session.add()
将记录添加到数据库会话中,最后通过db.session.commit()
提交会话以将记录保存到数据库。
读取记录:
from app import Movie
movie = Movie.query.first() # 获取第一条记录
print(movie.title) # 输出记录的title字段值
movies = Movie.query.all() # 获取所有记录
for movie in movies:
print(movie.title, movie.year) # 输出记录的title和year字段值
count = Movie.query.count() # 获取记录数量
print(count)
movie = Movie.query.get(1) # 根据主键获取指定记录
print(movie)
movie = Movie.query.filter_by(title='Mahjong').first() # 根据title字段过滤获取第一条记录
print(movie)
以上代码演示了如何使用查询方法从数据库中读取记录。我们使用Movie.query
来创建查询对象,并通过调用查询方法(如first()
、all()
、count()
等)获取相应的记录或记录数量。还可以使用过滤方法(如filter_by()
、filter()
等)对记录进行过滤。通过调用记录的属性,我们可以访问记录的字段值。
更新记录:
movie = Movie.query.get(2) # 获取要更新的记录
movie.title = 'WALL-E' # 更新记录的title字段值
movie.year = '2008'
db.session.commit() # 提交改动
以上代码演示了如何更新数据库中的记录。我们首先使用查询方法获取要更新的记录,然后直接对记录的属性赋予新的值,最后通过db.session.commit()
提交改动。
删除记录:
movie = Movie.query.get(1) # 获取要删除的记录
db.session.delete(movie) # 删除记录
db.session.commit() # 提交改动
以上代码演示了如何删除数据库中的记录。我们首先使用查询方法获取要删除的记录,然后使用db.session.delete()
方法将记录删除,最后通过db.session.commit()
提交改动。
这些是常见的数据库操作示例,你可以根据需要进行相应的操作。注意,在每次修改数据库后,都需要调用db.session.commit()
来提交改动,否则修改不会生效。
在程序中操作数据库可以通过视图函数进行。以下是在Watchlist中进行实际数据库操作的示例。
在主页视图中读取数据库记录:
@app.route('/')
def index():
user = User.query.first() # 读取用户记录
movies = Movie.query.all() # 读取所有电影记录
return render_template('index.html', user=user, movies=movies)
在index
视图函数中,我们使用User.query.first()
来获取用户记录,并使用Movie.query.all()
获取所有电影记录。然后将user
和movies
作为参数传递给模板index.html
。
在index.html
模板中,原来的name
变量被user
实例取代,因此需要将模板中的两处name
变量更新为user.name
属性:
<h1>{{ user.name }}'s Watchlist</h1>
...
<p>Welcome, {{ user.name }}!</p>
生成虚拟数据:
我们可以编写一个自定义命令函数,用于向数据库添加虚拟数据。以下是用于生成虚拟数据的命令函数:
import click
@app.cli.command()
def forge():
"""Generate fake data."""
db.create_all()
name = 'Grey Li'
movies = [
{'title': 'My Neighbor Totoro', 'year': '1988'},
{'title': 'Dead Poets Society', 'year': '1989'},
{'title': 'A Perfect World', 'year': '1993'},
{'title': 'Leon', 'year': '1994'},
{'title': 'Mahjong', 'year': '1996'},
{'title': 'Swallowtail Butterfly', 'year': '1996'},
{'title': 'King of Comedy', 'year': '1999'},
{'title': 'Devils on the Doorstep', 'year': '1999'},
{'title': 'WALL-E', 'year': '2008'},
{'title': 'The Pork of Music', 'year': '2012'},
]
user = User(name=name)
db.session.add(user)
for m in movies:
movie = Movie(title=m['title'], year=m['year'])
db.session.add(movie)
db.session.commit()
click.echo('Done.')
现在,通过运行flask forge
命令,可以将虚拟数据添加到数据库中。
请注意,对于每次修改数据库操作后,都需要调用db.session.commit()
来提交更改,以使更改生效。