web-dev-qa-db-ja.com

Flask-SQLAlchemyはテーブルに行が存在するかどうかをチェックします

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()

ありがとう。

23
Pav Sidhu

ユーザーが存在するかどうかを確認するだけなので、オブジェクト全体を照会する必要はありません。 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
35
davidism

最後に.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(...)よりも望ましい場合があります。

11
lyschoening
bool(User.query.filter_by(name='John Smith').first())

この名前のオブジェクトが存在しない場合は「False」を返し、存在する場合は「True」を返します。

2
Anna

ハイジャックを許しますが、ここで説明する手順を使用して、フィールドの一意性を確認するために次の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セッションを取得する方法はありますか?セッションがなければ、オブジェクト全体を読み込んでその存在を確認することは避けられないようです。

0
kblomqvist