如何从已加入的表中获取数据

时间:2016-04-10 19:08:07

标签: python join filter flask sqlalchemy

我有两张表itemsgames

@app.route('/collection/<username>/<int:page>/<platform>/<path:path>')    
def collection(username, page=1, platform='DMG', path=None):
    # first I get the user by his username
    user = User.query.filter_by(username=username).first()
    # then I get all items form the user and related games
    items = user.items.join(Game)
    # until now it works perfectly fine        
    # now I would like to obtain all titles from the joined table games
    game_titles = items.filter(Game.title).all()
    # but unfortunately I get only an empty list

缺少什么?

这是我的模特:

class Game(db.Model):
    __tablename__ = 'games'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64), index=True)
    publisher = db.Column(db.String(32), index=True)
    region = db.Column(db.String(3), index=True)
    code_platform = db.Column(db.String(3), index=True)
    code_identifier = db.Column(db.String(4), index=True)
    code_region = db.Column(db.String(3), index=True)
    code_revision = db.Column(db.String(1))
    code = db.Column(db.String(16), index=True, unique=True)
    year = db.Column(db.Integer)

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    items = db.relationship('Item', backref='game', lazy='dynamic')

    def __repr__(self):
        return '<Game %r>' % (self.title)


class Item(db.Model):
    __tablename__ = 'items'
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.String(8), index=True)
    cart = db.Column(db.Boolean)
    box = db.Column(db.Boolean)
    manual = db.Column(db.Boolean)

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    game_id = db.Column(db.Integer, db.ForeignKey('game.id'))

    def __repr__(self):
       return '<Collection %r>' % (self.user_id)

1 个答案:

答案 0 :(得分:1)

您有两种选择。使用SQLAlchemy ORM:

game_titles = [i.game.title for i in user.items]

为了提高效率,您可以应用joinedload优化:

game_titles = [i.game.title for i in user.items.options(joinedload(Item.game))]

或者,你可以使用SQLAlchemy核心,如果你关心的只是标题(而不是别的):

game_titles = user.items.join(Item.game).with_entities(Game.title).all()

如果您根本不关心用户,您甚至可以完全跳过提取用户:

game_titles = User.query.join(User.items).join(Item.game).filter(User.username == username).with_entities(Game.title).all()

另外,.filter.filter_by对应关系代数中的selection operator,而.with_entitiesdb.session.query(...)对应projection operator ,与你最初的假设相反。