gpt4 book ai didi

python - 具有三个相互关联的表的多对多(SqlAlchemy)

转载 作者:太空宇宙 更新时间:2023-11-04 02:14:42 26 4
gpt4 key购买 nike

我有三个表用户、设备和角色。我已经像这样创建了一个多对多的用户和设备关系;

#Many-to-Many relation between User and Devices
userDevices = db.Table("user_devices",
db.Column("id", db.Integer, primary_key=True),
db.Column("user_id", db.Integer, db.ForeignKey("user.id")),
db.Column("device_id", db.Integer, db.ForeignKey("device.id"))))

class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(60), index=True, unique=True)
devices = db.relationship("Device", secondary=userDevices, backref=db.backref('users'), lazy="dynamic")

class Device(db.Model):
__tablename__ = 'device'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(60), unique=True)

这很安静。我可以将设备 d1 分配给用户 u1 > d1.users.append(u1),并将用户分配给设备 > u1。 devices.append(d1)db.session.commit()

我更想要的是扩展表user_devices,增加一列作为role_id,这将是角色表的外键。这样这张表 user_devices 将清楚地描述特定 Device 上特定 UserRole。在表 user_devices 中添加一列 role_id 后,我将 Role 表描述为;

class Role(db.Model):
__tablename__ = 'role'

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(60), unique=True)
device = db.relationship("Device", secondary=userDevices, backref=db.backref('roles'), lazy="dynamic")

这样,我如何在设备 d1 上将角色 r1 分配给用户 u1 ?这是我尝试过的:

# First get the device, user and role 
deviceRow = db.session.query(Device).filter(Device.name=="d1").first()
userRow = db.session.query(User).filter(User.username=="u1").first()
roleRow = db.session.query(Role).filter(Role.name == "r1").first()
# Then add the user on that device
deviceRow.users.append(userRow)
deviceRow.roles.append(roleRow)

这会在表 user_devices 中创建两行

enter image description here

有什么方法可以像这样将两个属性添加到表中吗?;

deviceRow.users.append(userRow).roles.append(roleRow)

以便它在 commit() 之后只创建一行?

最佳答案

3 个实体的关联不再是简单的多对多关系。你需要的是 association object图案。为了更容易地处理关联,将其映射为模型类而不是简单的 Table:

class UserDevice(db.Model):
__tablename__ = "user_devices"

id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
device_id = db.Column(db.Integer, db.ForeignKey("device.id"), nullable=False)
role_id = db.Column(db.Integer, db.ForeignKey("role.id"), nullable=False)

__table_args__ = (db.UniqueConstraint(user_id, device_id, role_id),)

user = db.relationship("User", back_populates="user_devices")
device = db.relationship("Device")
role = db.relationship("Role", back_populates="user_devices")

class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(60), index=True, unique=True)
user_devices = db.relationship("UserDevice", back_populates="user")

class Role(db.Model):
__tablename__ = "role"

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(60), unique=True)
user_devices = db.relationship("UserDevice", back_populates="role")

要将用户与设备和角色相关联,请创建一个新的 UserDevice 对象:

device = db.session.query(Device).filter(Device.name == "d1").first()
user = db.session.query(User).filter(User.username == "u1").first()
role = db.session.query(Role).filter(Role.name == "r1").first()
assoc = UserDevice(user=user, device=device, role=role)
db.session.add(assoc)
db.session.commit()

请注意,ORM 关系不再是Device 等的简单集合,而是UserDevice 对象。这是一件好事:例如,当您遍历 user.user_devices 时,您会获得有关设备和用户在设备上的角色的信息。如果您确实希望在不需要角色信息的情况下也提供更简单的集合,则可以使用 associationproxy。 .

关于python - 具有三个相互关联的表的多对多(SqlAlchemy),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52920701/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com