Att*_*k68 2 python database many-to-many sqlalchemy
假设我有一组用户,每个用户都可以访问一组工具。相同的工具可能有许多用户具有访问权限,因此这是多对多关系:
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True)
tools = db.relationship("Tool", secondary=user_tool_assoc_table,
back_populates='users')
class Tool(db.Model):
__tablename__ = 'tool'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=False)
user_tool_assoc_table = db.Table('user_tool', db.Model.metadata,
db.Column('user', db.Integer, db.ForeignKey('user.id')),
db.Column('tool', db.Integer, db.ForeignKey('tool.id')))
Run Code Online (Sandbox Code Playgroud)
请注意,用户名是唯一的,但工具名不是。因此,User.name:Mike1并且User.name:Mike2可以访问Tool.name:Hammer,User.name:John1并且User.name:John2可以分别访问,并且可以使用Tool.name:Hammer相同的名称访问,但是每个名称都不同Tool.ids。
我想做一个约束,即在User.tools集合中永远不能有一个与另一个同名的工具,即
Tool如果已经存在具有该名称的用户,则用户不能创建一个新的内容作为其集合的一部分。Mike1无法创建一个称为Hammer其tools集合一部分的新工具。Tool存在于数据库不能被追加到tools,如果一个具有相同名称的设置已经存在的用户的集合,即John1的Hammer不能与Mike1共享,因为Mike1已有自己Hammer。James但是,Hammer由于他还没有锤子,因此可以创建一个新的。这样数据库中将有3个工具,Hammer每个工具都有一组不同的Users。Tool仅当a 至少具有一个时User,a 才会存在。SQLalchemy是否可以通过本机自动配置数据库以保持完整性?我不想编写自己的验证器规则,因为我可能会遗漏某些东西,并最终得到破坏我的规则的数据库。
问题是如何表达谓词“由ID标识的用户只有一个名称为NAME的工具”。用一个简单的表来表达,这当然很容易:
db.Table('user_toolname',
db.Column('user', db.Integer, db.ForeignKey('user.id'), primary_key=True),
db.Column('toolname', db.String, primary_key=True))
Run Code Online (Sandbox Code Playgroud)
同样非常清楚的是,仅凭这一点还不足以维持完整性,因为有关用户工具名的事实与实际工具之间没有任何联系。您的数据库可能会指出用户既有锤子又没有锤子。
最好以您user_tool_assoc_table或类似的方式来强制执行此操作,但是由于Tool.name它不是的主键的一部分,因此Tool您无法引用它。另一方面,由于您确实希望允许多个具有相同名称的工具共存,因此实际上,子集{id,name}是正确的键Tool:
class Tool(db.Model):
__tablename__ = 'tool'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String, primary_key=True)
Run Code Online (Sandbox Code Playgroud)
在id现在作为一个具有相同名称的工具之间的各种各样的“鉴别”。请注意,id在此模型中不必在全局范围内唯一,而在本地范围内name。使它仍然保持自动递增很方便,但是默认设置默认情况下autoincrement='auto'仅将单列整数主键视为具有自动递增行为,因此必须对其进行显式设置。
现在,还可以用定义user_tool_assoc_table,tool_name还具有一个附加约束,即用户只能使用一个具有给定名称的工具:
user_tool_assoc_table = db.Table(
'user_tool',
db.Column('user', db.Integer, db.ForeignKey('user.id')),
db.Column('tool', db.Integer),
db.Column('name', db.String),
db.ForeignKeyConstraint(['tool', 'name'],
['tool.id', 'tool.name']),
db.UniqueConstraint('user', 'name'))
Run Code Online (Sandbox Code Playgroud)
使用此模型和以下设置:
john = User(name='John')
mark = User(name='Mark')
db.session.add_all([john, mark])
hammer1 = Tool(name='Hammer')
hammer2 = Tool(name='Hammer')
db.session.add_all([hammer1, hammer2])
db.session.commit()
Run Code Online (Sandbox Code Playgroud)
这将成功:
john.tools.append(hammer1)
hammer2.users.append(mark)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)
由于违反了唯一约束,因此上述操作将失败:
john.tools.append(hammer2)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
640 次 |
| 最近记录: |