Anu*_*raz 5 python many-to-many sqlalchemy flask-sqlalchemy
我有三个表用户、设备和角色。我像这样创建了一个多对多关系 b/w User 和 Device;
#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)
Run Code Online (Sandbox Code Playgroud)
这很安静。我可以将设备分配d1给用户u1> d1.users.append(u1),将用户分配给设备 >u1.devices.append(d1)和db.session.commit()。
我想要更多的是user_devices用一列扩展表,作为role_id角色表的外键。以便此表user_devices将清楚地描述一个Role特定User于特定的Device. role_id在表中添加一列后,user_devices我将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")
Run Code Online (Sandbox Code Playgroud)
这样,我如何r1为u1设备上的用户分配角色d1?这是我尝试过的:
# 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)
Run Code Online (Sandbox Code Playgroud)
这将在表中创建两行 user_devices
有什么办法可以像这样将两个属性添加到表中吗?
deviceRow.users.append(userRow).roles.append(roleRow)
Run Code Online (Sandbox Code Playgroud)
以便在 commit() 之后只创建一行?
3 个实体的关联不再是简单的多对多关系。您需要的是关联对象模式。为了更容易处理关联,将其映射为模型类而不是简单的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")
Run Code Online (Sandbox Code Playgroud)
要将用户与设备和角色相关联,请创建一个新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()
Run Code Online (Sandbox Code Playgroud)
请注意,ORM 关系不再是Device等的简单集合,而是UserDevice对象。这是一件好事:user.user_devices例如,当您迭代时,您将获得有关设备和用户在其上的角色的信息。如果您确实希望在不需要角色信息的情况下也提供更简单的集合,则可以使用associationproxy.
| 归档时间: |
|
| 查看次数: |
2460 次 |
| 最近记录: |