SQLAlchemy InvalidRequest 添加到关系集合

Posted

技术标签:

【中文标题】SQLAlchemy InvalidRequest 添加到关系集合【英文标题】:SQLAlchemy InvalidRequest on adding to relationship collection 【发布时间】:2013-05-20 09:11:11 【问题描述】:

我在我的 Flask 项目中添加了一种“迁移”功能。最初我想添加与以下多对多相关的用户和角色:

users_to_roles_association_table = db.Table('users_to_roles',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
    db.Column('role_id', db.Integer, db.ForeignKey('roles.id')))

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, db.Sequence('user_id_seq'), primary_key=True)
    ..................
    roles = relationship('Role', secondary=users_to_roles_association_table, lazy='dynamic')

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, db.Sequence('role_id_seq'), primary_key=True)
    rolename = db.Column(db.String(128), unique=False)
    ..................

这是我的迁移up方法:

def up(self):
  try:
    user = User.query.filter_by(nickname='alp').first()

    if not user:
      user = User(email='some@email.com', nickname='admin', status=USER.Active)
      password = raw_input("Input password for user %s: " % user.nickname)
      user.set_password(password)
      db.session.add(user)

    role = Role.query.filter_by(rolename='Admin').first()
    if not role:
      role = Role(rolename='Admin')
      db.session.add(role)  //HERE

    if not user.is_in_role('Admin'):
      user.roles.append(role)


  except Exception, e:
    print "Rolling back changes"
    db.session.rollback()
    raise

当我运行它时,我遇到了一个异常:sqlalchemy.exc.InvalidRequestError: Object '<Role at 0x331db50>' is already attached to session '3' (this is '2') 如果我注释掉db.session.add(role) 行,错误就消失了,但Role 不会添加到数据库中。

我需要这个逻辑,因为其他一些记录可能在表中,所以我不能保证数据库中不存在特定角色。

如何处理这个错误?

【问题讨论】:

在向会话中添加任何内容之前尝试执行您的选择查询(即将role = Role.query... 行移到user = User.query 下方)- 有帮助吗? @DazWorrall,比你的建议,但我试过了。无论如何 - 我找到了解决方案,它与 db 变量有关。 【参考方案1】:

我找到了解决方案。由于对内部 Flask 架构的了解不足,我似乎踩到了耙子。

在我的迁移文件(我使用Flask-Evolution)的顶部有几行:

db = SQLAlchemy(current_app)
db.metadata.bind = main.db.engine

我使用这个变量db 来操作我的记录,但由于未知原因,它有自己的会话与我的不同(我在main.py 中定义了我自己的数据库处理程序:db = SQLAlchemy(app) )。当我用main.db.session... 替换像db.session.... 这样的行时,一切都变得正常了。如果有人能解释这种情况,我会很高兴。

【讨论】:

你现在可能已经明白了,但是SQLAlchemy 来自 Flask-SQLAlchemy,它与 SQLAlchemy 本身不同。虽然第二行可能会让您的绑定正确排列,但当您实例化 (Flask-)SQLAlchemy 两次时,您可能仍会获得第二个会话。在我们的应用程序中,我们在配置期间实例化一次SQLAlchemy,并在应用程序的其余部分使用相同的 db 变量。我会把from main import db放在你需要SQLAlchemy对象的任何地方,而不是db = SQLAlchemy(current_app)

以上是关于SQLAlchemy InvalidRequest 添加到关系集合的主要内容,如果未能解决你的问题,请参考以下文章

烧瓶-sqlalchemy 或 sqlalchemy

flask-sqlalchemy 和sqlalchemy的区别

flask-sqlalchemy

sqlalchemy.exc.NoSuchModuleError:无法加载插件:sqlalchemy.dialects:postgres

SQLAlchemy 是不是从同一连接重置 SQLAlchemy 会话之间的数据库会话?

cassandra删除数据问题