Flask-SQLAlchemyを使用してMySQLデータベースに接続するFlaskアプリケーションがあります。
テーブルに行が存在するかどうかを確認したいと思います。行が存在することを確認するためにクエリをどのように変更しますか:
db.session.query(User).filter_by(name='John Smith')
この質問 で解決策を見つけました。これはSQLAlchemyを使用しますが、Flask-SQLAlchemyの動作方法に適合しないようです。
from sqlalchemy.sql import exists
print session.query(exists().where(User.email == '...')).scalar()
ありがとう。
ユーザーが存在するかどうかを確認するだけなので、オブジェクト全体を照会する必要はありません。 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 = ?
2番目に示したクエリも正常に機能します。Flask-SQLAlchemyは、SQLAlchemyが作成できるクエリの種類を妨げるものは何もありません。これは、False
または上記のようなIDの代わりにTrue
またはNone
を返しますが、サブクエリを使用するため、わずかにより高価です。
exists = db.session.query(db.exists().where(User.name == 'davidism')).scalar()
SELECT EXISTS (SELECT *
FROM user
WHERE user.name = ?) AS anon_1
最後に.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(...)
よりも望ましい場合があります。
bool(User.query.filter_by(name='John Smith').first())
この名前のオブジェクトが存在しない場合は「False」を返し、存在する場合は「True」を返します。
ハイジャックを許しますが、ここで説明する手順を使用して、フィールドの一意性を確認するために次の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)])
ただし、2番目のパラメーターとしてdbセッションを必要としないAPIが欲しい
class Register(Form):
email = EmailField('Email', [Unique(User.email)])
モデルからdbセッションを取得する方法はありますか?セッションがなければ、オブジェクト全体を読み込んでその存在を確認することは避けられないようです。