Flask sqlalchemy 如何管理多对多关系中的附加信息

Flask sqlalchemy how to manage additional information in a many-to-many relationship

考虑以下多对多关系:

class Hashes(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  hash = db.Column(db.String, nullable=False, unique=True)

xref_hashes_users = db.Table("xref_hashes_users",
  db.Column('hash', db.ForeignKey('hashes.id'), primary_key=True),
  db.Column('user', db.ForeignKey('user.id'), primary_key=True))

class User(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  email = db.Column(db.String)
  hashes = db.relationship("Hashes", secondary="xref_hashes_users", backref="users")

假设我想让用户存储一些关于他们的散列的附加信息,也许是一个标签。这对我来说很有意义,因为这是一条关于哈希的特定于用户的信息,它将进入关联 table,如:

xref_hashes_users = db.Table("xref_hashes_users",
  db.Column('hash', db.ForeignKey('hashes.id'), primary_key=True),
  db.Column('user', db.ForeignKey('user.id'), primary_key=True),
  db.Column('label', db.String))

鉴于此模式,是否可以使用 ORM 来 add/remove/update 标签?我该怎么做?

看起来答案是使用关联对象来存储额外的数据。

https://docs-sqlalchemy.readthedocs.io/ko/latest/orm/basic_relationships.html#association-object

所以我的例子变成了:

class Hashes(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  hash = db.Column(db.String, nullable=False, unique=True)
  users = db.relationship("UserHashAssociation", back_populates="hashes")

class User(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  email = db.Column(db.String)
  hashes = db.relationship("UserHashAssociation", back_populates="users")

class UserHashAssociation(db.Model):
  __tablename__ = "xref_hashes_users"
  user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
  hash_id = db.Column(db.Integer, db.ForeignKey("hashes.id"), primary_key=True)
  label = db.Column(db.String)
  users = db.relationship("User", back_populates="hashes")
  hashes = db.relationship("Hashes", back_populates="users")

然后我可以像这样更新标签:

hash = Hashes(hash=hash_string)
user_hash_association = UserHashAssociation(label="foo", user_id=user.id)
hash.users.append(user_hash_association)
db.session.add(hash)
db.session.commit()