创建SQLAlchemy对象时的自定义操作

时间:2017-05-24 10:05:09

标签: python mysql sqlalchemy flask-sqlalchemy

假设我有一组用户,一组游戏,并且我跟踪用户是否在单独的表中完成了游戏(名称:' game_progress')。我想要的是,无论何时创建用户,“游戏进展”都是如此。表格会自动填入她的ID和“不”字样。反对所有可用的游戏。 (我知道我可以等到她开始游戏创建记录,但是,我需要这个用于完全不同的目的。)我将如何做到这一点?

我尝试使用after_insert()事件。但是,我无法检索要插入游戏进程的用户ID。我不想使用after_flush(即使我可以弄明白怎么做)因为它可能有点过分,因为用户创建操作并不经常发生。

class Game(db.Model):

    __tablename__ = 'games'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(30))

class User(db.Model):

    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(30))

class GameProgress(db.Model):

    __tablename__ = 'game_progress'
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
    game_id = db.Column(db.Integer, db.ForeignKey('games.id'), primary_key=True)
    game_finished = db.Column(db.Boolean)

@event.listens_for(User, "after_insert")
def after_insert(mapper, connection, target):
    progress_table = GameProgress.__table__
    user_id = target.id
    connection.execute(
        progress_table.insert().\
            values(user_id=user_id, game_id=1, game_finished=0)
    )

db.create_all()
game = Game(name='Solitaire')
db.session.add(game)
db.session.commit()
user = User(name='Alice')
db.session.add(user)
db.session.commit()

1 个答案:

答案 0 :(得分:0)

您根本不需要对触发器或事件侦听器执行任何操作,您只需设置关系,然后在User的构造函数中创建相关对象。只要您定义了关系(目前您没有这样做,您只添加了外键),那么您不需要User有id来设置关联对象。你的构造函数可以做这样的事情:

class User(db.Model): def __init__(self, all_games, **kwargs): for k,v in kwargs.items(): setattr(self, k, v) for game in all_games: self.game_progresses.append( GameProgress(game=game, \ user=self, game_finished=False) )

当您提交用户时,您还将提交一个GameProgress对象列表,每个游戏一个。但上述内容取决于您在所有对象上设置关系。您需要将以下内容添加到GameProgress类

game = relationship("Game", backref="game_progresses") user = relationship("User", backref="game_progresses")

在制作用户时向用户传递游戏列表:

all_games = dbs.query(Game).all() new_user = User(all_games=all_games, name="Iain")

完成后,您只需将GameProgress对象添加到已检测列表user.game_progresses中,您就不需要在第一次提交之前提交任何内容。 SQLA将追逐所有关系。基本上任何时候你需要直接使用id,你可以问问自己是否正确使用ORM,你很少需要。关于SQLA文档的ORM教程非常顺利。您可以将许多选项传递给关系和backrefs,以使级联执行您想要的任务。