如何使用 SQLAlchemy 将查询结果传递给变量(作为字符串)? [复制]
Posted
技术标签:
【中文标题】如何使用 SQLAlchemy 将查询结果传递给变量(作为字符串)? [复制]【英文标题】:How do I pass the result of a query to a variable (as a string) with SQLAlchemy? [duplicate] 【发布时间】:2020-05-10 02:48:18 【问题描述】:所以我有一个问题。我正在尝试验证密码对于简单的 Flask Web 应用程序是否有效。
这是我的代码的简化版本:
@app.route('/login', methods=['POST', 'GET'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user_password = db.session.query(User.password).filter(User.username == username).first()
if password != str(user_password):
return "The password is invalid."
else:
return "Login successful."
但这不起作用......它总是无效的,我想我知道为什么。 user_password 查询实际上不会将密码作为字符串返回。如果密码是 Hello1234,则返回 ('Hello1234',)。我需要的是 user_password 将返回的行作为字符串获取,以便我可以将其与用户输入进行比较。
我该怎么做?
【问题讨论】:
使用user_password[0]
- 即。 if password != user_password[0]:
BTW:但您可能必须在使用 [0]
之前检查您是否在 user_password
中获得任何值,因为您可能会得到空结果,然后 [0]
会出错。 if user_password and password != user_password[0]:
我必须敦促您不要将密码作为纯文本保存在您的数据库中。请不要延续循环。
确保您了解大数据库查询链接函数调用的返回类型。你没有得到一个字符串,这是一个带有字符串的元组,它是第一个成员。
@sleblanc 我必须让您知道,这仅用于测试目的,并且用于我学习时的个人项目。这不会投入生产。
代替.first()
,您可以使用.scalar()
检索第一行中的标量值,否则使用user_password[0]
选择元组中的第0个元素
【参考方案1】:
如果你得到元组('Hello1234',)
,那么使用索引[0]
从元组('Hello1234',)[0]
中获取第一个元素
if password != user_password[0]:
顺便说一句:我不知道当数据库中没有密码时它会给出什么 - 空元组或None
或引发错误但如果它给出空元组或None
那么你应该先检查有没有什么东西才能用[0]
if user_password and password != user_password[0]:
【讨论】:
是的,这行得通。 顺便说一句,我有一个查询要先搜索用户名,如果行数= 0,则用户不存在,如果> 1,则有问题,如果它= 1那么用户名存在,那么下一步就是检查密码是否有效。 您不必检查用户是否存在,因为当您获取密码(没有first()
)并检查len(user_password)
时应该得到相同的结果
当结果集为空时,.first()
将简单地返回 None
。注意:通常,您会希望使用.one_or_none()
,因为它会在意外返回多条记录时捕获编程错误,从而方便调试,而不是默默地丢弃额外的记录。
@sleblanc 谢谢你。我去看看。【参考方案2】:
当 SQLAlchemy 返回一行时,它从不返回单个值,而总是返回一个独立的行。因此,您必须从行中提取值,或将其与包含相同值的元组进行比较。
form_username = request.form['username']
form_password = request.form['password']
row = db.session.query(User.password).filter(User.username == form_username).one_or_none()
if row is None:
print("You are not part of our secret club")
else:
crypted_password = row[0]
# def check_password(plaintext, crypted) → bool
if check_password(form_password, crypted_password):
print("Access granted")
else:
print("Don't try to hack me!")
或者,您可以一次性检查用户名和密码。此方法效果不佳,因为密码检查功能通常需要知道与哈希密码一起存储在数据库中的盐。
整个“如果存在,则获取用户,然后验证密码”方案之所以存在,只是因为加密、哈希密码存储,否则,您应该尽量减少到数据库的往返行程,并在尽可能少的查询中完成所有事务。
form_username = request.form['username']
form_password = request.form['password']
row = db.session.query(User.name).filter(
User.username == form_username,
User.password == form_password).one_or_none()
if row is None:
print("Username or password invalid.")
else:
print("Welcome aboard, %s.".format(row[0]))
【讨论】:
以上是关于如何使用 SQLAlchemy 将查询结果传递给变量(作为字符串)? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Flask SQLAlchemy amp;Peewee 的查询结果转换成 json
如何将 Sqlalchemy ORM 查询结果转换为包含关系的单个联接表?
SQLAlchemy 如何将未映射的 COUNT(*) 作为查询的结果?