【问题标题】:SQLAlchemy session error while creating object with m2m relation使用 m2m 关系创建对象时出现 SQLAlchemy 会话错误
【发布时间】:2020-08-06 12:55:14
【问题描述】:

我是 SQLAlchemy 和 Flask 的新手。我正在尝试使用 m2m 关系创建一个对象(book)并将一个现有对象(tag_2)附加到该关系:

book = Book(title='title')

tag_1 = Tag(name='tag')
book.tags.append(tag_1)     # New tag works well

tag_2 = Tag.query.get(123)  # Get existed tag by id
print(tag_2)                # >>> Tag #123
book.tags.append(tag_2)     # ERROR: Object '<Tag at ...>' is already attached to session '1'

self.session.add(book)
self.session.commit()

创建新的相关对象没有问题,但无法指向现有对象。

我的模型:

book_tags = db.Table('book_tags', db.metadata,
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('book_id', db.Integer, db.ForeignKey('book.id'))
)


class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), unique=True)


class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(300), nullable=False)
    tags = db.relationship('Tag', secondary=book_tags)

我使用 sqlite 作为数据库。

【问题讨论】:

  • 您是否在单个数据库会话中完成所有这些操作?当您使用一个会话选择Tag 然后您尝试使用不同的会话存储它时,通常会发生此错误。穷人的调试方法是打印会话。
  • 我使用 flask_resty 作为 REST 框架。我相信在这种情况下它只会创建一个会话。我会尝试创建一个新的来选择Tag
  • 你只需要一个,一样的。从您对下面答案的评论中,您已经有 2 个会话。确保每个请求只创建一个会话。如果您发布了控制器的外观,将会有所帮助。
  • 是的,你是对的。谢谢!

标签: python flask orm sqlalchemy


【解决方案1】:

您似乎使用不同的self.session 来获取Tag 和获取Book,然后您尝试将Tag 附加到。为了能够将对象 A 附加到对象 B,它们必须都存在于同一会话中。

很难说出您是如何创建会话的,因为您的帖子只显示了与它一起操作的代码,但请确保您只有一个会话。

【讨论】:

    【解决方案2】:
    tags = db.relationship(
        'Tag',
        secondary=book_tags,
        backref=db.backref('book', lazy='dynamic')
    )
    

    您需要在 m2m 关系中添加 backref,因为
    使用 backref 只会在另一端自动创建关系属性。 backref='book' 有点类似于在 Tag 类中显式地设置 book = db.relationship('book') (+ back 人口)。使用 backref() 对象,您可以将参数传递给该关系。

    【讨论】:

    • 同样的错误,但使用Book 而不是Tagsqlalchemy.exc.InvalidRequestError: Object '&lt;Book at 0x1057c9510&gt;' is already attached to session '1' (this is '2')
    • 这是问题is already attached to session '1' (this is '2')的根本原因,您需要在单个会话中执行这两项操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    • 2020-12-26
    • 2015-03-30
    • 1970-01-01
    • 2014-11-09
    相关资源
    最近更新 更多