2012-09-26 6 views
22

Ho bisogno di aiuto nella creazione della query SqlAlchemy.SqlAlchemy e Flask, come interrogare la relazione molti-a-molti

Sto facendo un progetto Flask dove sto usando SqlAlchemy. Ho creato 3 tavoli: Restaurant, Dish e restaurant_dish nel mio file 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) 

Ho aggiunto dati al tavolo restaurant_dish e dovrebbe funzionare correttamente. Dove ho bisogno di aiuto è capire come ottenere correttamente un piatto usando il ristorante. Raw SQL sarebbe qualcosa di simile a questo:

SELECT dish_id FROM restaurant_dish WHERE restaurant_id == id 

Quello che sono riuscito a ottenere fatto, ma non funziona:

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

Grazie per l'aiuto e ho anche apprezzare il tutorial che mi può puntare nella giusta direzione (la documentazione ufficiale mi passa per la testa).

risposta

43

La semantica della relazione non sembra corretta. Penso che dovrebbe essere qualcosa di simile:

class Restaurant(db.Model): 
    ... 

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

Poi, per recuperare tutti i piatti per un ristorante, si può fare:

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

Questo dovrebbe generare una query come:

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

Grazie. Questo era il modo corretto per farlo. :) – cancerballs

+4

Dopo aver cercato per ore, 'Dish.restaurant.any' era esattamente quello che stavo cercando! +1 a te! – Matthew

+1

questa risposta è migliore di qualsiasi documentazione. – user455318