- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
使用Flask-SQLAlchemy管理数据库 Flask-SQLAlchemy是一个Flask扩展,它简化了在Flask应用程序中对SQLAlchemy的使用。SQLAlchemy是一个强大的关系数据库框架,支持一些数据库后端。提供高级的ORM和底层访问数据库的本地SQL功能。 和其他扩展一样,通过pip安装Flask-SQLAlchemy:
1
|
(venv) $ pip
install
flask-sqlalchemy
|
在Flask-SQLAlchemy,数据库被指定为URL。表格列出三个最受欢迎的数据库引擎url的格式:
在这些URL中,hostname是指托管MySQL服务的服务器,可能是本地(localhost)又或是远程服务器。数据库服务器可以托管多个数据库,所以database指出要使用的数据库名。数据库需要身份验证,username和 password是数据库用户凭证。 注:> SQLite数据库没有服务,所以hostname、username和password可以缺省且数据库是一个磁盘文件名。 应用程序数据库URL必须在Flask配置对象中的SQLALCHEMY_DATABASE_URI键中进行配置。另一个有用的选项是SQLALCHEMY_COMMIT_ON_TEARDOWN,可以设置为True来启用自动提交数据库更改在每个请求中。查阅Flask-SQLAlchemy文档获取更多其他配置选项.
1
2
3
4
5
6
7
8
9
10
|
from
flask.ext.sqlalchemy
import
SQLAlchemy
basedir
=
os.path.abspath(os.path.dirname(__file__))
app
=
Flask(__name__)
app.config[
'SQLALCHEMY_DATABASE_URI'
]
=
\
'sqlite:///'
+
os.path.join(basedir,
'data.sqlite'
)
app.config[
'SQLALCHEMY_COMMIT_ON_TEARDOWN'
]
=
True
db
=
SQLAlchemy(app)
|
由SQLAlchemy实例化的db对象表示数据库且提供访问Flask-SQLAlchemy的所有功能.
模型定义 模型是指由应用程序使用的持久化实体。在ORM的背景下,一个模型通常是一个带有属性的Python类,其属性与数据库表的列相匹配对应。Flask-SQLAlchemy数据库实例提供了一个基类以及一组辅助类和函数用于定义它的结构.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
Role(db.Model):
__tablename__
=
'roles'
id
=
db.Column(db.Integer, primary_key
=
True
)
name
=
db.Column(db.String(
64
), unique
=
True
)
def
__repr__(
self
):
return
'<Role %r>'
%
self
.name
class
User(db.Model):
__tablename__
=
'users'
id
=
db.Column(db.Integer, primary_key
=
True
)
username
=
db.Column(db.String(
64
), unique
=
True
, index
=
True
)
def
__repr__(
self
):
return
'<User %r>'
%
self
.username
|
__tablename__类变量定义数据库中表的名称。如果__tablename__缺省Flask-SQLAlchemy会指定默认的表名,但是这些缺省名称不遵守使用复数命名的约定,所以最好是显式命名表名。其余的变量是模型的属性,被定义为db.Column类的实例。 传给db.Column构造函数的第一个参数是数据库列的类型也就是模型属性的数据类型。表格5-2列出一些可用的列的类型,也是用于模型中的Python类型.
最常见的SQLAlchemy列类型 db.Column剩余的参数为每个属性指定了配置选项.
最常见的SQLAlchemy列选项 注:Flask-SQLAlchemy需要给所有的模型定义主键列,通常命名为id。 两个模型都包含了repr()方法来给它们显示一个可读字符串,虽然不是完全必要,不过用于调试和测试还是很不错的.
关系 关系数据库通过使用关系在不同的表中建立连接。关系图表达了用户和用户角色之间的简单关系。这个角色和用户是一对多关系,因为一个角色可以从属于多个用户,而一个用户只能拥有一个角色。 下面的模型类展示了中表达的一对多关系.
1
2
3
4
5
6
7
|
class
Role(db.Model):
# ...
users
=
db.relationship(
'User'
, backref
=
'role'
)
class
User(db.Model):
# ...
role_id
=
db.Column(db.Integer, db.ForeignKey(
'roles.id'
))
|
关系通过使用外键来连接两行。添加给User模型的role_id列被定义为外键,且建立关系。db.ForeignKey()的参数roles.id指定的列应该理解为在roles表的行中持有id值的列。 添加到Role模型的users属性表现了关系的面向对象的观点。给定Role类的实例,users属性会返回一组连接到该角色的用户。指定给db.relationship()的第一个参数表明模型中关系的另一边。如果类还未定义,这个模型可以作为字符串提供。 注意:之前在segmentdefault中遇到的问题,后来粗略阅读了SQLAlchemy的源码。ForeignKey类的column接收三种类型的参数,一种是“模型名.属性名”;一种是“表名.列名”,最后一种没看明白,下次试着用一下。 db.relationship()的backref参数通过给User模型增加role属性来定义反向关系。这个属性可以替代role_id访问Role模型,是作为对象而不是外键。 大多数情况下db.relationship()可以定位自己的外键关系,但是有时候不能确定哪个列被用作外键。例如,如果User模型有两个或更多列被定义为Role的外键,SQLAlchemy将不知道使用两个中的哪一个。每当外键配置模棱两可的时候,就必须使用额外参数db.relationship()。下标列出一些常用配置选项用于定义关系:
常用SQLAlchemy关系选项 。
建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 5a来切换到这个版本的应用程序。 除了一对多关系还有其他种类关系。一对一关系可以表述为前面描述的一对多关系,只要将db.relationship()中的uselist选项设置为False,“多”就变为“一”了。多对一关系也可表示为将表反转后的一对多关系,或表示为外键和db.relationship()定义在“多”那边。最复杂的关系类型,多对多,需要一个被称作关联表的额外表。你将在第十二章学习多对多关系.
数据库操作 学习怎样使用模型的最好方式就是使用Python shell。以下部分将介绍最常见的数据库操作.
创建表 。
首先要做的第一件事情就是指示Flask-SQLAlchemy基于模型类创建数据库。db.create_all()函数会完成这些:
1
2
3
|
(venv) $ python hello.py shell
>>>
from
hello
import
db
>>> db.create_all()
|
如果你检查应用程序目录,你会发现名为data.sqlite的新文件,SQLite数据库名在配置中给出。如果数据库已存在db.create_all()函数不会重新创建或更新数据库表。这会非常的不方便当模型被修改且更改需要应用到现有的数据库时。更新现有的数据库表的蛮力解决方案是先删除旧的表:
1
2
|
>>> db.drop_all()
>>> db.create_all()
|
不幸的是,这种方法有个不受欢迎的副作用就是摧毁旧的数据库中的所有数据。更新数据库问题的解决方案会在这章快结束的时候介绍.
插入行 。
下面的示例会创建新的角色和用户:
1
2
3
4
5
6
7
|
>>>
from
hello
import
Role, User
>>> admin_role
=
Role(name
=
'Admin'
)
>>> mod_role
=
Role(name
=
'Moderator'
)
>>> user_role
=
Role(name
=
'User'
)
>>> user_john
=
User(username
=
'john'
, role
=
admin_role)
>>> user_susan
=
User(username
=
'susan'
, role
=
user_role)
>>> user_david
=
User(username
=
'david'
, role
=
user_role)
|
模型的构造函数接受模型属性的初始值作为关键字参数。注意,甚至可以使用role属性,即使它不是一个真正的数据库列,而是一对多关系的高级表示。这些新对象的id属性没有显式设置:主键由Flask-SQLAlchemy来管理。到目前为止对象只存于Python中,他们还没有被写入数据库。因为他们的id值尚未分配:
1
2
3
|
>>>
print
(admin_role.
id
)
None
>>>
print
(mod_role.
id
)
None
>>>
print
(user_role.
id
)
None
|
修改数据库的操作由Flask-SQLAlchemy提供的db.session数据库会话来管理。准备写入到数据库中的对象必须添加到会话中:
1
2
3
4
5
6
|
>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)
|
或,更简洁的:
1
2
|
>>> db.session.add_all([admin_role, mod_role, user_role,
... user_john, user_susan, user_david])
|
1
|
>>> db.session.commit()
|
再次检查id属性;这个时候它们都已经被设置好了:
1
2
3
4
5
6
|
>>>
print
(admin_role.
id
)
1
>>>
print
(mod_role.
id
)
2
>>>
print
(user_role.
id
)
3
|
注:db.session数据库会话和第四章讨论的Flask会话没有任何联系。数据库会话也叫事务。 数据库会话在数据库一致性上是非常有用的。提交操作会原子性地将所有添加到会话中的对象写入数据库。如果在写入的过程发生错误,会将整个会话丢弃。如果你总是在一个会话提交相关修改,你必须保证避免因部分更新导致的数据库不一致的情况.
注:数据库会话也可以回滚。如果调用db.session.rollback(),任何添加到数据库会话中的对象都会恢复到它们曾经在数据库中的状态。 修改行 。
数据库会话中的add()方法同样可以用于更新模型。继续在同一shell会话中,下面的示例重命名“Admin”角色为“Administrator”:
1
2
3
|
>>> admin_role.name
=
'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()
|
注意:不过貌似我们在做更新操作的时候都不使用db.session.add(),而是直接使用db.session.commit()来提交事务。 删除行 。
数据库会话同样有delete()方法。下面的示例从数据库中删除“Moderator”角色:
1
2
|
>>> db.session.delete(mod_role)
>>> db.session.commit()
|
注意删除,和插入更新一样,都是在数据库会话提交后执行.
返回行 。
Flask-SQLAlchemy为每个模型类创建一个query对象。最基本的查询模型是返回对应的表的全部内容:
1
2
3
4
|
>>> Role.query.
all
()
[<Role u
'Administrator'
>, <Role u
'User'
>]
>>> User.query.
all
()
[<User u
'john'
>, <User u
'susan'
>, <User u
'david'
>]
|
使用过滤器可以配置查询对象去执行更具体的数据库搜索。下面的例子查找所有被分配“User”角色的用户:
1
2
|
>>> User.query.filter_by(role
=
user_role).
all
()
[<User u
'susan'
>, <User u
'david'
>]
|
对于给定的查询还可以检查SQLAlchemy生成的原生SQL查询,并将查询对象转换为一个字符串:
1
2
3
|
>>>
str
(User.query.filter_by(role
=
user_role))
'SELECT users.
id
AS users_id, users.username AS users_username,
users.role_id AS users_role_id FROM users WHERE :param_1
=
users.role_id'
|
如果你退出shell会话,在前面的示例中创建的对象将不能作为Python对象而存在,但可继续作为行记录存在各自的数据库表中。如果你开始一个全新的shell会话,你必须从它们的数据库行中重新创建Python对象。下面的示例执行查询来加载名字为“User”的用户角色.
1
|
>>> user_role
=
Role.query.filter_by(name
=
'User'
).first()
|
过滤器如filter_by()通过query对象来调用,且返回经过提炼后的query。多个过滤器可以依次调用直到需要的查询配置结束为止.
下面展示一些查询中常用的过滤器.
在需要的过滤器已经全部运用于query后,调用all()会触发query执行并返回一组结果,但是除了all()以外还有其他方式可以触发执行。常用SQLAlchemy查询执行器:
关系的原理类似于查询。下面的示例从两边查询角色和用户之间的一对多关系:
1
2
3
4
5
|
>>> users
=
user_role.users
>>> users
[<User u
'susan'
>, <User u
'david'
>]
>>> users[
0
].role
<Role u
'User'
>
|
此处的user_role.users查询有点小问题。当user_role.users表达式在内部调用all()时通过隐式查询执行来返回用户的列表。因为查询对象是隐藏的,是不可能通过附加查询过滤器进一步提取出来。在这个特定的例子中,它可能是用于按字母排列顺序返回用户列表。在下面的示例中,被lazy = 'dynamic'参数修改过的关系配置的查询是不会自动执行的.
app/models.py:动态关系 。
1
2
3
4
|
class
Role(db.Model):
# ...
users
=
db.relationship(
'User'
, backref
=
'role'
, lazy
=
'dynamic'
)
# ...
|
用这种方式配置关系,user_roles.user查询还没有执行,所以可以给它增加过滤器:
1
2
3
4
|
>>> user_role.users.order_by(User.username).
all
()
[<User u
'david'
>, <User u
'susan'
>]
>>> user_role.users.count()
2
|
最后此篇关于Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程的文章就讲到这里了,如果你想了解更多关于Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我需要开发一个简单的网站,我通常使用 bootstrap CSS 框架,但是我想使用 Gumbyn,它允许我使用 16 列而不是 12 列。 我想知道是否: 我可以轻松地改变绿色吗? 如何使用固定布局
这个问题在这里已经有了答案: 关闭 13 年前。 与直接编写 PHP 代码相比,使用 PHP 框架有哪些优点/缺点?
我开发了一个 Spring/JPA 应用程序:服务、存储库和域层即将完成。 唯一缺少的层是网络层。我正在考虑将 Playframework 2.0 用于 Web 层,但我不确定是否可以在我的 Play
我现有的 struts Web 应用程序具有单点登录功能。然后我将使用 spring 框架创建一个不同的 Web 应用程序。然后想要使用从 struts 应用程序登录的用户来链接新的 spring 应
我首先使用Spark框架和ORMLite处理网页上表单提交的数据,在提交中文字符时看到了unicode问题。我首先想到问题可能是由于ORMLite,因为我的MySQL数据库的字符集已设置为使用utf8
我有一个使用 .Net 4.5 功能的模块,我们的应用程序也适用于 XP 用户。所以我正在考虑将这个 .net 4.5 依赖模块移动到单独的项目中。我怎样才能有一个解决方案,其中有两个项目针对不同的版
我知道这是一个非常笼统的问题,但我想我并不是真的在寻找明确的答案。作为 PHP 框架的新手,我很难理解它。 Javascript 框架,尤其是带有 UI 扩展的框架,似乎通过将 JS 代码与设计分开来
我需要收集一些关于现有 ORM 解决方案的信息。 请随意编写任何编程语言。 你能谈谈你用过的最好的 ORM 框架吗?为什么它比其他的更好? 最佳答案 我使用了 NHibernate 和 Entity
除了 Apple 的 SDK 之外,还有什么强大的 iPhone 框架可供开始开发?有没有可以加快开发时间的方法? 最佳答案 此类框架最大的是Three20 。 Facebook 和许多其他公司都使用
有人可以启发我使用 NodeJS 的 Web 框架吗?我最近开始从免费代码营学习express js,虽然一切进展顺利,但我对express到底是什么感到困惑。是全栈框架吗?纯粹是为了后端吗?我发现您
您可以推荐哪种 Ajax 框架/工具包来构建使用 struts 的 Web 应用程序的 GUI? 最佳答案 我会说你的 AJAX/javascript 库选择应该较少取决于你的后端是如何实现的,而更多
我有生成以下错误的 python 代码: objc[36554]: Class TKApplication is implemented in both /Library/Frameworks/Tk.
首先,很抱歉,如果我问的问题很明显,因为我没有编程背景,那我去吧: 我想运行一系列测试场景并在背景部分声明了几个变量(我打印它们以仔细检查它们是否已正确声明),第一个是整数,另外两个字符串为你可以看到
在我们承担的一个项目中,我们正在寻找一个视频捕获和录制库。我们的基础工作(基于 google 搜索)表明 vlc (libvlc)、ffmpeg (libavcodec) 和 gstreamer 是三
我试过没有运气的情况下寻找某种功能来杀死/中断Play中的正常工作!框架。 我想念什么吗?还是玩了!实际没有添加此功能? 最佳答案 Java stop类中没有像Thread方法那样的东西,由于种种原因
我们希望在我们的系统中保留所有重大事件的记录。例如,在数据库可能存储当前用户状态的地方,事件日志应记录对该状态的所有更改以及更改发生的时间。 事件记录工具应该尽可能接近于事件引发器的零开销,应该容纳结
那里有 ActionScript 2.0/3.0 的测试框架列表吗? 最佳答案 2010-05-18 更新 由于这篇文章有点旧,而且我刚刚收到了赞成票,因此可能值得提供一些更新的信息,这样人们就不会追
我有一个巨大的 numpy 数组列表(一维),它们是不同事件的时间序列。每个点都有一个标签,我想根据其标签对 numpy 数组进行窗口化。我的标签是 0、1 和 2。每个窗口都有一个固定的大小 M。
我是 Play 的新手!并编写了我的第一个应用程序。这个应用程序有一组它依赖的 URL,从 XML 响应中提取数据并返回有效的 URL。 此应用程序需要在不同的环境(Dev、Staging 和 Pro
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我是一名优秀的程序员,十分优秀!