赵走x博客
网站访问量:151455
首页
书籍
软件
工具
古诗词
搜索
登录
Flask 实战:41、电子邮件进阶实践
Flask 实战:40、使用事务邮件服务SendGird
Flask 实战:39、使用Flask-Mail发送电子邮件
Flask 实战:38、数据库进阶实践
Flask 实战:37、更新数据库表
Flask 实战:36、定义关系
Flask 实战:35、在视图函数里操作数据库
Flask 实战:34、数据库操作:CRUD
Flask 实战:33、使用Flask-SQLAlchemy管理数据库
Flask 实战:32、ORM魔法
Flask 实战:31、数据库的分类
Flask 实战:30、单个页面多个表单
Flask 实战:29、单个表单多个提交按钮
Flask 实战:28、使用Flask-CKEditor集成富文本编辑器
Flask 实战:27、多文件上传
Flask 实战:26、文件上传
Flask 实战:25、自定义验证器
Flask 实战:24、使用宏渲染表单
Flask 实战:23、设置错误消息语言
Flask 实战:22、处理表单数据
Flask 实战:21、使用Flask-WTF处理表单
Flask 实战:20、HTML表单
Flask 实战:19、模板进阶实践
Flask 实战:18、模板结构组织
Flask 实战:17、模板辅助工具
Flask 实战:16、模板基本用法
Flask 实战:15、HTTP进阶实践
Flask 实战:14、Flask上下文
Flask 实战:13、HTTP响应
Flask 实战:12、HTTP请求
Flask 实战:11、请求响应循环
Flask 实战:10、Flask与MVC架构
Flask 实战:9、模板与静态文件
Flask 实战:8、Flask命令
Flask 实战:7、URL与端点
Flask 实战:6、项目配置
Flask 实战:5、Flask扩展
Flask 实战:4、Python Shell
Flask 实战:3、启动开发服务器
Flask 实战:2、Hello,Flask!
Flask 实战:1、初识Flask
Flask 实战:33、使用Flask-SQLAlchemy管理数据库
资源编号:75884
Python Web
Flask Web开发实战:入门、进阶与原理解析
热度:87
扩展Flask-SQLAlchemy集成了SQLAlchemy,它简化了连接数据库服务器、管理数据库操作会话等各类工作,让Flask中的数据处理体验变得更加轻松。
扩展Flask-SQLAlchemy集成了SQLAlchemy,它简化了连接数据库服务器、管理数据库操作会话等各类工作,让Flask中的数据处理体验变得更加轻松。 首先使用Pipenv安装Flask-SQLAlchemy及其依赖(主要是SQLAlchemy): ``` $ pipenv install flask-sqlalchemy ``` 下面在示例程序中实例化Flask-SQLAlchemy提供的SQLAlchemy类,传入程序实例app,以完成扩展的初始化: ``` from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) db = SQLAlchemy(app) ``` 为了便于使用,我们把实例化扩展类的对象命名为db。这个db对象代表我们的数据库,它可以使用Flask-SQLAlchemy提供的所有功能。 >提示 虽然我们要使用的大部分类和函数都由SQLAlchemy提供,但在Flask-SQLAlchemy中,大多数情况下,我们不需要手动从SQLAlchemy导入类或函数。在sqlalchemy和sqlalchemy.orm模块中实现的类和函数,以及其他几个常用的模块和对象都可以作为db对象的属性调用。当我们创建这样的调用时,Flask-SQLAlchemy会自动把这些调用转发到对应的类、函数或模块。 # 1、连接数据库服务器 DBMS通常会提供数据库服务器运行在操作系统中。要连接数据库服务器,首先要为我们的程序指定数据库URI(Uniform Resource Identifier,统一资源标识符)。数据库URI是一串包含各种属性的字符串,其中包含了各种用于连接数据库的信息。 > 附注 URI代表统一资源标识符,是用来标示资源的一组字符串。URL是它的子集。在大多数情况下,这两者可以交替使用。 表5-2是一些常用的DBMS及其数据库URI格式示例。  表5-2 常用的数据库URI格式 在Flask-SQLAlchemy中,数据库的URI通过配置变量SQLALCHEMY_DATABASE_URI设置,默认为SQLite内存型数据库(sqlite:///:memory:)。SQLite是基于文件的DBMS,不需要设置数据库服务器,只需要指定数据库文件的绝对路径。我们使用app.root_path来定位数据库文件的路径,并将数据库文件命名为data.db,如代码清单5-1所示。 代码清单5-1 app.py:配置数据库URI ``` import os ... app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///' + os.path.join(app.root_path, 'data.db')) ``` 在生产环境下更换到其他类型的DBMS时,数据库URL会包含敏感信息,所以这里优先从环境变量DATABASE_URL获取(注意这里为了便于理解使用了URL,而不是URI)。 >注意 SQLite的数据库URI在Linux或macOS系统下的斜线数量是4个;在Windows系统下的URI中的斜线数量为3个。内存型数据库的斜线固定为3个。 SQLite数据库文件名不限定后缀,常用的命名方式有foo.sqlite,foo.db,或是注明SQLite版本的foo.sqlite3。 设置好数据库URI后,在Python Shell中导入并查看db对象会获得下面的输出: ``` >>> from app import db >>> db
``` 安装并初始化Flask-SQLAlchemy后,启动程序时会看到命令行下有一行警告信息。这是因为Flask-SQLAlchemy建议你设置SQLALCHEMY_TRACK_MODIFICATIONS配置变量,这个配置变量决定是否追踪对象的修改,这用于Flask-SQLAlchemy的事件通知系统。这个配置键的默认值为None,如果没有特殊需要,我们可以把它设为False来关闭警告信息: ``` app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False ``` Flask-SQLAlchemy计划在3.0版本默认将这个配置键设为False,目前最新版本为2.3.2。 # 2、定义数据库模型 用来映射到数据库表的Python类通常被称为数据库模型(model),一个数据库模型类对应数据库中的一个表。定义模型即使用Python类定义表模式,并声明映射关系。所有的模型类都需要继承Flask-SQLAlchemy提供的db.Model基类。本章的示例程序是一个笔记程序,笔记保存到数据库中,你可以通过程序查询、添加、更新和删除笔记。在代码清单5-2中,我们定义了一个Note模型类,用来存储笔记。 代码清单5-2 app.py:定义Note模型 ``` class Note(db.Model): id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) ``` 在上面的模型类中,表的字段(列)由db.Column类的实例表示,字段的类型通过Column类构造方法的第一个参数传入。在这个模型中,我们创建了一个类型为db.Integer的id字段和类型为db.Text的body列,分别存储整型和文本。常用的SQLAlchemy字段类型如表5-3所示。  表5-3 SQLAlchemy常用的字段类型 字段类型一般直接声明即可,如果需要传入参数,你也可以添加括号。对于类似String的字符串列,有些数据库会要求限定长度,因此最好为其指定长度。虽然使用Text类型可以存储相对灵活的变长文本,但从性能上考虑,我们仅在必须的情况下使用Text类型,比如用户发表的文章和评论等不限长度的内容。 一般情况下,字段的长度是由程序设计者自定的。尽管如此,也有一些既定的约束标准,比如姓名(英语)的长度一般不超过70个字符,中文名一般不超过20个字符,电子邮件地址的长度不超过254个字符,虽然各主流浏览器支持长达2048个字符的URL,但在网站中用户资料设置的限度一般为255。尽管如此,对于超过一定长度的Email和URL,比如20个字符,会在显示时添加省略号的形式。显示的用户名(username)允许重复,通常要短一些,以不超过36个字符为佳。当然,在程序中,你可以根据需要来自由设定这些限制值。 当你在数据库模型类中限制了字段的长度后,在接收对应数据的表单类字段里,也需要使用Length验证器来验证用户的输入数据。 默认情况下,Flask-SQLAlchemy会根据模型类的名称生成一个表名称,生成规则如下: ``` Message --> message # 单个单词转换为小写 FooBar --> foo_bar # 多个单词转换为小写并使用下划线分隔 ``` Note类对应的表名称即note。如果你想自己指定表名称,可以通过定义__tablename__属性来实现。字段名默认为类属性名,你也可以通过字段类构造方法的第一个参数指定,或使用关键字name。根据我们定义的Note模型类,最终将生成一个note表,表中包含id和body字段。 除了name参数,实例化字段类时常用的字段参数如表5-4所示。  表5-4 常用的SQLAlchemy字段参数 > 提示 不需要在所有列都建立索引。一般来说,取值可能性多(比如姓名)的列,以及经常被用来作为排序参照的列(比如时间戳)更适合建立索引。 在实例化字段类时,通过把参数primary_key设为True可以将其定义为主键。在我们定义的Note类中,id字段即表的主键(primary key)。主键是每一条记录(行)独一无二的标识,也是模型类中必须定义的字段,一般命名为id或pk。 # 3、创建数据库和表 如果把数据库(文件)看作一个仓库,为了方便取用,我们需要把货物按照类型分别放置在不同货架上,这些货架就是数据库中的表。创建模型类后,我们需要手动创建数据库和对应的表,也就是我们常说的建库和建表。这通过对我们的db对象调用create_all()方法实现: ``` $ flask shell >>> from app import db >>> db.create_all() ``` > 注意 如果你将模型类定义在单独的模块中,那么必须在调用db.create_all()方法前导入相应模块,以便让SQLAlchemy获取模型类被创建时生成的表信息,进而正确生成数据表。 通过下面的方式可以查看模型对应的SQL模式(建表语句): ``` >>> from sqlalchemy.schema import CreateTable >>> print(CreateTable(Note.__table__)) CREATE TABLE note ( id INTEGER NOT NULL, body TEXT, PRIMARY KEY (id) ) ``` 数据库和表一旦创建后,之后对模型的改动不会自动作用到实际的表中。比如,在模型类中添加或删除字段,修改字段的名称和类型,这时再次调用create_all()也不会更新表结构。如果要使改动生效,最简单的方式是调用db.drop_all()方法删除数据库和表,然后再调用db.create_all()方法创建,后面会具体介绍。 我们也可以自己实现一个自定义flask命令完成这个工作,如代码清单5-3所示。 代码清单5-3 demos/database/app.py:用于创建数据库和表的flask命令 ``` import click ... @app.cli.command() def initdb(): db.create_all() click.echo('Initialized database.') ``` 在命令行下输入flask inintdb即可创建数据库和表: ``` $ flask initdb Initialized database. ``` 对于示例程序来说,这会在database目录下创建一个data.db文件。 在开发程序或是部署后,我们经常需要在Python Shell中手动操作数据库(生产环境需注意备份),对于一次性操作,直接处理即可。对于需要重用的操作,我们可以编写成Flask命令、函数或是模型类的类方法。