2012-05-12 8 views
2

自分の好きなシリーズを持つことができるユーザーがいて、シリーズが外部キーであるエピソードがあり、好きなシリーズのユーザーからすべてのエピソードを取得しようとしています。 私はFlask-SQLAlchemyを使用しています。SQLAlchemy:特定のユーザーのfavorite_seriesからすべてのエピソードを取得

データベース:

db = SQLAlchemy(app) 

# cross table for user-series 
favorite_series = db.Table('favorite_series', 
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')), 
    db.Column('series_id', db.Integer, db.ForeignKey('series.id')) 
) 

# user 
class User(db.Model): 
    __tablename__ = 'user' 
    id = db.Column(db.Integer, primary_key=True) 
    favorite_series = db.relationship('Series', secondary=favorite_series, 
     backref=db.backref('users', lazy='dynamic')) 

# series 
class Series(db.Model): 
    __tablename__ = 'series' 
    id = db.Column(db.Integer, primary_key=True) 

# episode 
class Episode(db.Model): 
    __tablename__ = 'episode' 
    id = db.Column(db.Integer, primary_key=True) 
    series_id = db.Column(db.Integer, db.ForeignKey('series.id')) 
    series = db.relationship('Series', 
     backref=db.backref('episodes', lazy='dynamic')) 

友達がSQL

select user_id,series.name,episode.name from (favorite_series left join series on favorite_series.series_id = series.id) left join episode on episode.series_id = series.id where user_id=1; 

Altoughで私を助け、私はSQLAlchemyのAPIでそれをしたいが、それは作業を取得するために管理することはできません。

EDIT

私の最終的な作業の結果:私はフラスコについては知らないが、フラスコSQLAlchemyののドキュメントから、ORMので、それは宣言型の使用思わ

episodes = Episode.query.filter(Episode.series_id.in_(x.id for x in g.user.favorite_series)).filter(Episode.air_time!=None).order_by(Episode.air_time) 
+0

あなたはSQLAlchemyのORMを使用していますか?フラスコのsqlalchemyは私の考えだ... – jadkik94

+0

私は本当にこれで新しいです:)あなたは私に教えてください:) '>>> s = Series.query.get(1) >>> s.episodes ' – TrueFurby

答えて

5

まず、テーブル名を宣言しているようですか? はまた、ORMを悩まの全体のポイントは、あなたがSQLクエリを記述する必要はありませんです:

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import orm 
import sqlalchemy as db 
Base = declarative_base() 

favorite_series = db.Table('favorite_series', Base.metadata, 
    db.Column('user_id', db.Integer, db.ForeignKey('User.id')), 
    db.Column('series_id', db.Integer, db.ForeignKey('Series.id')) 
) 
class Episode(Base): 
    __tablename__ = 'Episode' 
    id = db.Column(db.Integer, primary_key=True) 
    season = db.Column(db.Integer) 
    episode_num = db.Column(db.Integer) 
    series_id = db.Column(db.Integer, db.ForeignKey('Series.id')) 

    def __init__(self, season, episode_num, series_id): 
     self.season = season 
     self.episode_num = episode_num 
     self.series_id = series_id 

    def __repr__(self): 
     return self.series.title + \ 
       ' S' + str(self.season) + \ 
       'E' + str(self.episode_num) 

class Series(Base): 
    __tablename__ = 'Series' 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String) 
    episodes = orm.relationship('Episode', backref='series') 

    def __init__(self, title): 
     self.title = title 

    def __repr__(self): 
     return self.title 

class User(Base): 
    __tablename__ = 'User' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String) 
    favorite_series = orm.relationship('Series', 
     secondary=favorite_series, backref='users') 

    def __init__(self, name): 
     self.name = name 

    def __repr__(self): 
     return self.name 

今、あなたは自分のオブジェクトの属性にアクセスし、同期してDBあなたを維持し、発行したSQL錬金術の契約をさせることができますクエリ。最後に

engine = db.create_engine('sqlite:///:memory:') 
session = orm.sessionmaker(bind=engine)() 
Base.metadata.create_all(engine) 

lt = User('Ludovic Tiako') 
the_wire = Series('The Wire') 
friends = Series('Friends') 
session.add_all([lt, the_wire, friends]) 
session.commit() # need to commit here to generate the id fields 

tw_s01e01 = Episode(1,1,the_wire.id) 
tw_s01e02 = Episode(1,2,the_wire.id) 
f_s01e01 = Episode(1,1,friends.id) 
f_s01e02 = Episode(1,2,friends.id) 
f_s01e03 = Episode(1,3,friends.id) 

session.add_all([tw_s01e01, tw_s01e02, 
       f_s01e01, f_s01e02, f_s01e03]) 
session.commit() 


the_wire.episodes # > [The Wire S1E1, The Wire S1E2] 
friends.episodes # > [Friends S1E1, Friends S1E2, Friends S1E3] 

、あなたの質問に答えるために:

lt.favorite_series.append(the_wire) 
session.commit() 
lt.favorite_series # > [The Wire] 
[s.episodes for s in lt.favorite_series] # >> [[The Wire S1E1, The Wire S1E2]] 
+0

しかし私は言及しなかったいくつかの他のフィルタを適用する必要があります。 私はユーザーを気にしないときにこれを使用します: 'episodes = Episode.air_time> = t.strftime( '%Y%m%d'))。order_by(Episode.air_time)' – TrueFurby

+0

そして、特定のユーザーのエピソードに同じフィルターと順序を使用したいと思います。 – TrueFurby

+0

いったん 'fav_episodes = [lt.favorite_seriesのs.episodes.id]' あなたのクエリ 'query.filter(Episode.id.in_(fav_episodes))に' – ludaavics

0

。そして、セッションがあるはずです。私はそれがdb.sessionからあなたにアクセスできると思います。

これらの前提条件が満たされている場合はとにかく、これはあなたがそれを行うべきかです:

query = db.session.query(User.id, Series.name, Episode.name).filter((Episode.series_id == Series.id) & \ 
    (User.id == favorite_series.c.user_id) & (Series.id == favorite_series.c.id) & \ 
    (User.id == 1)) 
results = query.all(); 

それはあなたが提供される正確なクエリではないかもしれませんが、同じことを行う必要があります。

UPDATE:私はちょうどgithubにフラスコSQLAlchemyのコードをチェックし、dbは、セッションオブジェクトを返しますself.session = self.create_scoped_session(session_options)によって作成されたsession属性を持っているSQLAlchemyのインスタンス、と思われます。これはうまくいくはずです。

また、ではないこと、私はそれが意味するだろうかわからないが、あなたは、彼らのBaseQueryを使用しない、ことを実行して...

正確に何をすべきかを知っているマニュアルを参照してください。

+0

'db'がメタデータのように見えるので、セッションはそこにはありません。セッションオブジェクトは 'sessionmaker'によって作成されます。 – wberry

+0

@wberry 'db'は' SQLAlchemy'のインスタンスです。コードを参照してください。私はリンクを追加しました、私はこれがセッションにアクセスする方法だと思います。 – jadkik94

+0

これはスローします:AttributeError: 'テーブル'オブジェクトは属性 'user_id'を持っていません – TrueFurby

関連する問題