2012-06-09 4 views
3

여기 다시 당신의 도움이 거의 필요하지 않습니다.Flask-SQLAlchemy - 마지막으로 보았던 시리즈에서 처음으로 보지 못한 에피소드

내가 본 시리즈 중 첫 번째 에피소드를 사용자가 좋아하는 시리즈에서 검색하고 싶습니다 (다음에 시청할 시리즈) 그리고 마지막으로 시청 한 시리즈를 검색하고 싶습니다.

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 
import logging 
from datetime import datetime 
from sqlalchemy.ext.associationproxy import association_proxy 

app = Flask(__name__) 
db = SQLAlchemy(app) 

logging.basicConfig() 

watched_episodes = db.Table('watched_episodes', 
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')), 
    db.Column('episode_id', db.Integer, db.ForeignKey('episode.id')) 
) 


class User(db.Model): 
    __tablename__ = 'user' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String) 
    favorite_series = association_proxy('user_series', 'serie') 
    watched_episodes = db.relationship('Episode', secondary=watched_episodes, 
     backref=db.backref('users', lazy='dynamic')) 

    def __repr__(self): 
     return '<User {0}>'.format(self.name) 

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


class UserSerie(db.Model): 
    __tablename__ = 'user_series' 
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), \ 
     primary_key=True) 
    serie_id = db.Column(db.Integer, db.ForeignKey('serie.id'), \ 
     primary_key=True) 
    last_watched = db.Column(db.DateTime) 
    user = db.relationship("User", \ 
     backref=db.backref("user_series", cascade="all, delete-orphan")) 
    serie = db.relationship("Serie") 

    def __init__(self, serie=None, user=None, last_watched=None): 
     self.user = user 
     self.serie = serie 
     self.last_watched = datetime.now() 


class Serie(db.Model): 
    __tablename__ = 'serie' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String) 

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

    def __repr__(self): 
     return '<Serie {0}>'.format(self.name) 


class Episode(db.Model): 
    __tablename__ = 'episode' 
    id = db.Column(db.Integer, primary_key=True) 
    air_time = db.Column(db.DateTime) 
    seas_num = db.Column(db.Integer) 
    epis_num = db.Column(db.Integer) 
    serie_id = db.Column(db.Integer, db.ForeignKey('serie.id')) 
    serie = db.relationship('Serie', 
     backref=db.backref('episodes', lazy='dynamic')) 

    def __init__(self, air_time, seas_num, epis_num): 
     self.air_time = air_time 
     self.seas_num = seas_num 
     self.epis_num = epis_num 

    def __repr__(self): 
     return '<Episode S{0}E{0}>'.format(self.seas_num, self.epis_num) 

u1 = User('user1') 

s1 = Serie('Serie1') 
s2 = Serie('Serie2') 

e1 = Episode(datetime(2008, 05, 30), 1, 1) 
e1.serie = s1 
e2 = Episode(datetime(2008, 06, 05), 1, 1) 
e2.serie = s1 
e3 = Episode(datetime(2008, 06, 10), 1, 1) 
e3.serie = s1 

e4 = Episode(datetime(2012, 01, 01), 1, 1) 
e4.serie = s2 
e5 = Episode(datetime(2012, 02, 12), 1, 1) 
e5.serie = s2 
e6 = Episode(datetime(2012, 03, 23), 1, 1) 
e6.serie = s2 

u1.favorite_series.extend([s1, s2]) 

db.session.add(u1) 
db.session.add(s1) 
db.session.add(s2) 
db.session.add(e1) 
db.session.add(e2) 
db.session.add(e3) 
db.session.add(e4) 
db.session.add(e5) 
db.session.add(e6) 
db.create_all() 
db.session.commit() 

logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) 

sub = db.session.query(UserSerie.serie_id, UserSerie.last_watched).\ 
    group_by(UserSerie.serie_id).subquery() 

sub2 = db.session.query(Episode).\ 
    filter(Episode.serie_id.in_(x.id for x in u1.favorite_series)).\ 
    order_by(Episode.air_time).\ 
    group_by(Episode.serie_id).subquery() 

shows = db.session.query(Serie, sub2).\ 
    outerjoin(sub, Serie.id == sub.c.serie_id).\ 
    outerjoin(sub2).\ 
    filter(Serie.id.in_(\ 
     x.id for x in u1.favorite_series)).\ 
    order_by(sub.c.last_watched) 

for s in shows: 
    print s 

이 반환 있지만 :

(<Serie Serie1>, 3, datetime.datetime(2008, 6, 10, 0, 0), 1, 1, 1) 
(<Serie Serie2>, 6, datetime.datetime(2012, 3, 23, 0, 0), 1, 1, 2) 

하지만이 같은 개체로 에피소드를 원하는 : 사전에 어떤 도움

(<Serie Serie1>, <Episode S01E01>) 
(<Serie Serie2>, <Episode S01E01>) 

감사합니다.

+0

가 followmy.tv 클론을 만들기

문제점은 다음의 코드로 해결되었다? ;) – ThiefMaster

+0

그건 부적절합니다. 나는 배우기 위해 이것을하고 있습니다. 파이썬, 플라스크, SQLAlchemy 등 – TrueFurby

+0

그것은 주로 호기심이었다. – ThiefMaster

답변

1

오케이. 아무도 나를 도울 수 없었다. 나는 다시 Artificial 친구에게 도움을 받았다.

episodes = Episode.query.subquery() 
userseries = UserSerie.query.subquery() 
# Get the min air time for each of the favorite series. 
min_air_times = db.session.query(
     Serie.id.label('serie_id'), 
     db.func.min(episodes.c.id).label('id') 
    ).filter(
     Serie.id.in_(x.id for x in u1.favorite_series) 
    ).outerjoin(
     userseries, 
     Serie.id == userseries.c.serie_id 
    ).outerjoin(
     episodes, 
     Serie.id == episodes.c.serie_id 
    ).filter(
     ~episodes.c.id.in_(x.id for x in u1.watched_episodes) 
    ).filter(
     episodes.c.seas_num != 0 
    ).order_by(
     desc(userseries.c.last_watched) 
    ).group_by(
     Serie.id 
    ).subquery() 
# Select the serie and episode. 
shows = db.session.query(
     Serie, 
     Episode 
    ).join(
     Episode, 
     Episode.serie_id == Serie.id 
    ).join(
     min_air_times, 
     db.and_(
      min_air_times.c.serie_id == Serie.id, 
      min_air_times.c.id == Episode.id 
     ) 
    ).all() 
+0

친구 Artificial에 SO에 가입하라고 해보지 그래? ;) – silpol