假设我有一组用户,一组游戏,并且我跟踪用户是否在单独的表中完成了游戏(名称:' 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()
答案 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,以使级联执行您想要的任务。