在 Flask-SQLAlchemy 中联表查询

在 Flask-SQLAlchemy 中联表查询,第1张

SQLAlchemy 是一个功能强大的 ORM 。 Flask-SQLAlchemy 是一个 Flask 插件,它让我们在 Flask 框架中使用 SQLAlchemy 变得更容易。

本篇介绍我在使用 Flask-SQLAlchemy 21 时进行联表查询的一些经验

这里有两个表,account 表保存帐号 ID 和昵称,bind 表保存 account 之间的绑定关系。

对应的 Model 如下:

先来看一个简单的例子:查询 gameuid 1000 账号下绑定的所有帐号。

看一看生成的 SQL 语句:

这里的联表查询使用的是 WHERE 语句。如果希望使用 JOIN 语句,可以这样写:

可以看出,现在生成的 SQL 语句已经使用 JOIN 语句了。但上面的语意有点奇怪,既然已经在 query 中使用了 Bind 和 Account,后面再 join 一次 Account 总觉得有点多余。那么 SQLAlchemy 如何选择 JOIN 的时候谁先谁后呢?看看这个错误就知道了:

这个错误显然说明,query 中参数的顺序很重要,第一个参数所代表的 table 就是 JOIN 时放在前面的那个 table。因此,此处 JOIN 的目标应该是 Account, 而不应该是 Bind 自身。

上面的例子已经解决了大多数需求了。我们再来看看分页。在 Flask-SQLAlchemy 中封装了一个 paginate 方法,可以方便地将查询记录进行分页:

报错的原因是 dbsessionquery 默认返回的是 ormQuery 对象,这个对象并不包含 paginate 方法。要解决这个问题,需要修改 Flask-SQLAlchemy 的源码。

找到 SQLAlchemy 对象的 __init__ 定义,在其中加入 session_options['query_cls'] = BaseQuery 即可:

在 Flask-SQLAlchemy 提供的 Model 对象中,可以使用 Modelquery 这样的语法来直接得到一个查询对象,这是由于 Flask-SQLAlchemy 中存在一个 _QueryProperty 类,每次调用 Model__get__ 时,会自动生成一个基于当前 session 的 query 对象:

使用 Modelquery 得到的这个 query 对象可以直接进行 JOIN *** 作,得到的结果是 Model 对象。这样就方便多了:

转换成 SQL 是这样的:

可以看出,这样的查询结果和使用 dbsessionquery 并没有什么不同。由于返回的是 Model 对象,使用上可能还更加方便了。

如何使用 Modelqueryjoin 语法得到部分字段呢?这里可以使用 SQLAlchemy 提供的 with_entities 方法:

注意,列表中的项 (2, '玩家10001') 并不是标准的 Python tuple。你如果查看它的类型,会发现一个奇怪的名称: <class 'sqlalchemyutil_collectionsresult'> 。它是一个 AbstractKeyedTuple 对象,拥有一个 keys() 方法,这样可以很容易将其转换成 dict :

想了解 AbstractKeyedTuple ,可以看看这篇文档 New KeyedTuple implementation dramatically faster 。

除了筛选字段外,还可以用另一个方法获取多个 Model 的记录。那就是,返回两个 Model 的所有字段:

使用上面的语法直接返回 Account 和 Bind 对象,可以进行更加灵活的 *** 作。

要联结超过 2 张以上的表,可以直接在 join 得到的结果之后链式调用 join 。也可以在 filter 的结果后面链式调用 join 。join 和 filter 返回的都是 query 对象,因此可以无限链式调用下去。

写完查询后,应该打印生成的 SQL 语句查看一下有没有性能问题。

app = Flask(__name__)

appconfig['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:19931218@localhost/test'appconfig['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = Truedb = SQLAlchemy(app)class User(dbModel):

    __tablename__ = 'user'

    id = dbColumn(dbInteger, primary_key=True)

    username = dbColumn(dbString(80), unique=True)

    email = dbColumn(dbString(120), unique=True)

    def __init__(self, username, email):

        selfusername = username

        selfemail = email

    def __repr__(self):

        return '<User %r>' % selfusernamefrom sql_learn import db,User

import pymysql

dbcreate_all()#创建相应的表

#user_Susan = User(username = 'Susan',email = '6666663@qqcom')

#dbsessionadd(user_Susan)

#user_Susanusername = 'Susan_2'

#dbsessionadd(user_Susan)

#dbsessioncommit()

#print(dbsessionquery(User,Userid,Userusername)all())#这里返回的是一个元组,每一个对象还是一个元组,包含User类,id,username

#print(Userqueryfilter_by(username = 'Susan')all())#flask的查询对象返回User的对象user = Userqueryfilter_by(username = 'Susan')first()userusername = 'Susan_wifi'dbsessionadd(user)

dbsessioncommit()

既然你认为已经提交成功了。(但是这只是你认为:证明很简单。打开数据库看一下有没有数据)

假使已经添加成功。那么问题肯定出在 Memberqueryfilter_by(username=str(formusernamedata))first()

这个查询。调试看一下

以上就是关于在 Flask-SQLAlchemy 中联表查询全部的内容,包括:在 Flask-SQLAlchemy 中联表查询、在python3下怎样用flask-sqlalchemy对mysql数据库 *** 作、Flask-sqlalchemy、Flask-WTF结合查询的一个疑问等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9873770.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存