SQLAlchemy 多对多关联 class

SQLAlchemy many-to-many association class

我有以下两个classes(简体):

class User(db.Model):
    __tablename__ = "AppUser"
    user_id = db.Column(db.Integer, primary_key=True)

class Task(db.Model):
    __tablename__ = "Task"
    task_id = db.Column(db.Integer, primary_key=True)

我想通过多对多关联加入它们,但除了主键之外还要存储一个附加列:

class Solved(db.Model):
    __tablename__ = "Solved"
    user_id = db.Column(db.Integer, db.ForeignKey("AppUser.user_id"), primary_key=True)
    task_id = db.Column(db.Integer, db.ForeignKey("Task.task_id"), primary_key=True)
    solved_at = db.Column(db.DateTime, default=datetime.utcnow)

我选择了 class 而不是 table 因为 SQLAlchemy 文档建议在我必须存储额外的列时使用 class。

我的问题是我不能 "join" 他们。 我尝试了以下方法:

将引用直接添加到关联table:

task = db.relationship("Task", backref="users")
user = db.relationship("AppUser", backref="tasks")

添加对用户和任务的引用 class:

class User:
    [...]
    tasks = db.relationship("Solved", backref="users")

class Task:
    [...]
    users = db.relationship("Solved", backref="tasks")

它们都不起作用。 令我惊讶的是,如果我将 Solved class 更改为 db.Table 对象,它会起作用。 我想尝试关联 class 因为我使用引用已解决但不接受 db.Table 对象的子查询。

我想做的是将 "solved" 个任务添加到列表中:

u = User.query.get([...])
t = Task.query.get([...])
u.tasks.append(t)
db.session.add(u)
db.session.commit()

编辑:

当我检查一个元素是否已经是 "Solved":

# My models have name fields
u.tasks.filter_by(name="abc")

我收到以下错误:

AttributeError: '_AssociationList' object has no attribute 'filter_by'

当我将新元素添加到列表时:

u.tasks.append(t)
db.session.add(u) # These two steps work
db.session.commit() # Error

sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers.  Original exception was: relationship 'user' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)   

如上文所述,它适用于简单的 db.Table 关联,但不适用于 class.

关联

我也试过像here (SQLAlchemy docs)这样的关联代理,但我得到了和上面一样的错误。

我能够解决问题。 我主要复制了 association proxy tutorial from the official doc 以下是给其他挣扎的人的一些陷阱和提示:

  • 在您想加入的 class 之后写下您的协会 class。 (对我们大多数人来说很明显,但检查一下也无妨)
  • 向您的关联添加 __init__ 功能 class!
  • 仔细检查您的反向引用、class 和 table 名称。 我自己没有仔细研究过什么时候使用哪个关键字,但大多数时候都是你的错误。