Pytanie SqlAlchemy and Flask, jak wyszukiwać relacje wiele do wielu


Potrzebuję pomocy w tworzeniu zapytania SqlAlchemy.

Robię projekt Flask, w którym używam SqlAlchemy. Stworzyłem 3 tabele: Restaurant, Dish i restaurant_dish w moim pliku models.py.

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)

Dodałem dane do tabeli restaurant_dish i powinno działać poprawnie. Gdzie potrzebuję pomocy, to zrozumienie, jak prawidłowo uzyskać Dish za pomocą restauracji. Surowy SQL będzie wyglądał mniej więcej tak:

SELECT dish_id FROM restaurant_dish WHERE restaurant_id == id

Co udało mi się zrobić, ale nie działa:

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

Dzięki za pomoc i doceniam tutoriale, które mogą wskazać mi właściwy kierunek (oficjalna dokumentacja przechodzi mi przez głowę).


26
2017-09-26 01:41


pochodzenie




Odpowiedzi:


Semantyczny związek nie wygląda dobrze. Myślę, że powinno to być coś takiego:

class Restaurant(db.Model):
    ...

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

Następnie, aby odzyskać wszystkie potrawy w restauracji, możesz:

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

Powinno to wygenerować zapytanie takie jak:

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

47
2017-09-26 03:37



Dziękuję Ci. To był właściwy sposób, aby to zrobić. :) - cancerballs
Po wyszukiwaniu godzin, Dish.restaurant.any było dokładnie tym, czego szukałem! +1 do ciebie! - Matthew
ta odpowiedź jest lepsza niż jakakolwiek dokumentacja. - user455318
Co się stanie, jeśli będę musiał zapytać wszystkie restauracje, które korzystają z danej potrawy? AKA, odwrotne pobieranie. - Devy
Czy jest jakiś sposób robienia Dish.restaurants.any(thisrestaurant) kiedy ten restaurator jest intencją Restauracji? Mógłbym to zrobić Dish.restaurants.any(id=thisrestaurant.id) ale to brzmi trochę trudniej - somenxavier