web-dev-qa-db-ja.com

SqlAlchemyとFlask、多対多の関係をクエリする方法

SqlAlchemyクエリの作成についてサポートが必要です。

私はSqlAlchemyを使用しているFlaskプロジェクトを実行しています。models.pyファイルにRestaurant、Dish、restaurant_dishの3つのテーブルを作成しました。

restaurant_dish = db.Table('restaurant_dish',
    db.Column('dish_id', db.Integer, db.ForeignKey('dish.id')),
    db.Column('restaurant_id', db.Integer, db.ForeignKey('restaurant.id'))
)

class Restaurant(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(64), index = True)

    restaurant_dish = db.relationship('Dish', secondary=restaurant_dish,
        backref=db.backref('dishes', lazy='dynamic'))


class Dish(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(64), index = True)
    info = db.Column(db.String(256), index = True)

Restaurant_dishテーブルにデータを追加しましたが、正しく機能するはずです。私が助けを必要としているのは、レストランを使って料理を正しく得る方法を理解することです。生のSQLは次のようになります。

SELECT dish_id FROM restaurant_dish WHERE restaurant_id == id

私が何とか成し遂げたが機能しなかったもの:

x = Restaurant.query.filter_by(Restaurant.restaurant_dish.contains(name)).all()

助けてくれてありがとう、そして私を正しい方向に導くことができるチュートリアルにも感謝します(公式ドキュメントは私の頭を超えています)。

28
cancerballs

関係のセマンティクスが正しくありません。私はそれが次のようなものであるべきだと思います:

class Restaurant(db.Model):
    ...

    dishes = db.relationship('Dish', secondary=restaurant_dish,
        backref=db.backref('restaurants'))

次に、レストランのすべての料理を取得するには、次のようにします。

x = Dish.query.filter(Dish.restaurants.any(name=name)).all()

これにより、次のようなクエリが生成されます。

SELECT dish.*
FROM dish
WHERE
    EXISTS (
        SELECT 1
        FROM restaurant_dish
        WHERE
            dish.id = restaurant_dish.dish_id
            AND EXISTS (
                SELECT 1
                FROM restaurant
                WHERE
                    restaurant_dish.restaurant_id = restaurant.id
                    AND restaurant.name = :name
            )
    )
55
sayap