我有一个Flask应用程序,它使用Flask-SQLAlchemy连接到MySQL数据库。
我希望能够检查表中是否存在行。我如何修改这样的查询以检查行是否存在:
db.session.query(User).filter_by(name='John Smith')
我在this question上找到了一个使用SQLAlchemy的解决方案,但似乎不符合Flask-SQLAlchemy的工作方式:
from sqlalchemy.sql import exists
print session.query(exists().where(User.email == '...')).scalar()
感谢。
答案 0 :(得分:32)
由于您只想查看用户是否存在,因此您不希望查询整个对象。只查询id,如果标量返回不是None,则存在。
exists = db.session.query(User.id).filter_by(name='davidism').scalar() is not None
SELECT user.id AS user_id
FROM user
WHERE user.name = ?
您展示的第二个查询也可以正常工作,Flask-SQLAlchemy不会阻止SQLAlchemy可以进行任何类型的查询。这会返回False
或True
而非None
或上面的ID,但稍微更昂贵,因为它使用子查询。
exists = db.session.query(db.exists().where(User.name == 'davidism')).scalar()
SELECT EXISTS (SELECT *
FROM user
WHERE user.name = ?) AS anon_1
答案 1 :(得分:11)
在另一个.exists()
中将session.query()
个查询包裹在最后一个scalar()
。 SQLAlchemy将生成一个返回EXISTS
或True
的优化False
查询。
exists = db.session.query(
db.session.query(User).filter_by(name='John Smith').exists()
).scalar()
SELECT EXISTS (SELECT 1
FROM user
WHERE user.name = ?) AS anon_1
虽然由于子查询而可能更昂贵,但是查询的内容更清楚。它也可能优于db.exists().where(...)
,因为它选择一个常量而不是整行。
答案 2 :(得分:1)
bool(User.query.filter_by(name='John Smith').first())
如果不存在具有该名称的对象,则返回“ False”,如果存在则返回“ True”。
答案 3 :(得分:0)
原谅劫持但是...在这里给出的指示我做了以下WTForm验证器来检查该字段的唯一性
class Unique(object):
def __init__(self, column, session, message="Already exists."):
self.column = column
self.session = session
self.message = message
def __call__(self, form, field):
if field.data == field.object_data:
return # Field value equals to existing value. That's ok.
model = self.column.class_
query = model.query.filter(self.column == field.data).exists()
if self.session.query(query).scalar():
raise ValidationError(self.message)
它会像这样使用
class Register(Form):
email = EmailField('Email', [Unique(User.email, db.session)])
但是,我希望API不需要db session作为第二个参数
class Register(Form):
email = EmailField('Email', [Unique(User.email)])
有没有办法从模型中获取数据库会话?没有会话,似乎不可能避免加载整个对象来检查它的存在。
答案 4 :(得分:-2)
认为在大卫的答案中有一个错字,这对我有用:
exists = db.session.query(**User**).filter_by(name='davidism').scalar() is not None