database - SQLAlchemy:来自多个表的外键(多对多)
问题描述
我在我的烧瓶应用程序中使用了flask-sqlalchemy orm,它是关于智能家居传感器和演员的(为了简单起见,我们称它们为Nodes
.
现在我想存储一个Event
绑定的对象Nodes
,以检查它们的状态和其他或相同Nodes
的状态,如果第一个状态已达到阈值,则应使用给定值设置。
此外,可以从/forGroups
或中检查或设置状态Scenes
。所以我有三个不同的外键要检查,另外三个要设置。每种类型都可以有多个类型,每个Event
.
这是一个示例代码,其中包含db.Model
我希望存储在 s 和伪代码中的内容Event
:
db = SQLAlchemy()
class Node(db.Model):
id = db.Column(db.Integer, primary_key=True)
value = db.Column(db.String(20))
# columns snipped out
class Group(db.Model):
id = db.Column(db.Integer, primary_key=True)
value = db.Column(db.String(20))
# columns snipped out
class Scene(db.Model):
id = db.Column(db.Integer, primary_key=True)
value = db.Column(db.String(20))
# columns snipped out
class Event(db.Model):
id = db.Column(db.Integer, primary_key=True)
# The following columns may be in a intermediate table
# but I have no clue how to design that under these conditions
constraints = # list of foreignkeys from diffrent tables (Node/Group/Scene)
# with threshold per key
target = # list of foreignkeys from diffrent tables (Node/Group/Scene)
# with target values per key
最后,我希望能够检查我的任何s 是否为 true 以相应Event
地设置绑定Node
// Group
。Scene
这可能是数据库设计问题(而不是 sqlalchemy),但我想在这里利用 sqla orm 的优势。
受这个和那个答案的启发,我试图深入挖掘,但关于 SO 的其他问题是关于更具体的问题或一对多关系。
非常感谢任何提示或设计技巧。谢谢!
解决方案
我最终在使用和代码行之间进行了权衡。我的第一个想法是尽可能多地保存代码(DRY)并定义尽可能少的表。
正如 SQLAlchemy 本身在他们的一个示例中指出的那样,支持“通用外键”只是因为它经常被请求,而不是因为它是一个好的解决方案。使用较少的数据库功能,应用程序必须注意关键约束。
另一方面,他们说,在数据库中拥有更多表不会影响数据库性能。
所以我尝试了一些方法并找到了一个适合我用例的好方法。我没有使用用于多对多关系的“普通”中间表,而是使用另一个 SQLAlchemy 类,该类在两侧都有两个一对多关系来连接两个表。
class Event(db.Model):
id = db.Column(db.Integer, primary_key=True)
noodles = db.relationship('NoodleEvent', back_populates='events')
# columns snipped out
def get_as_dict(self):
return {
"id": self.id,
"nodes": [n.get_as_dict() for n in self.nodes]
}
class Node(db.Model):
id = db.Column(db.Integer, primary_key=True)
value = db.Column(db.String(20))
events = db.relationship('NodeEvent', back_populates='node')
# columns snipped out
class NodeEvent(db.Model):
ev_id = db.Column('ev_id', db.Integer, db.ForeignKey('event.id'), primary_key=True)
n_id = db.Column('n_id', db.Integer, db.ForeignKey('node.id'), primary_key=True)
value = db.Column('value', db.String(200), nullable=False)
compare = db.Column('compare', db.String(20), nullable=True)
node = db.relationship('Node', back_populates="events")
events = db.relationship('Event', back_populates="nodes")
def get_as_dict(self):
return {
"trigger_value": self.value,
"actual_value": self.node.status,
"compare": self.compare
}
权衡是每次我在该关系上绑定一个新表时,我都必须定义一个新类。但是使用“通用外键”方法,我还必须检查 ForeignKey 的来源。一天结束时做同样的工作。
通过我的get_as_dict()
功能,我可以非常方便地访问相关数据。
推荐阅读
- c# - 无法将 System.Data.DataRowView 类型的对象转换为 System.Windows.Controls.ListViewItem 类型
- python-3.x - 在 Windows 10 上安装 pycrypto 时出现问题
- javascript - React-table 中的表单
- laravel - 我们可以在 Laravel 5.6 中使用 Laravel 5.7 电子邮件验证吗?
- javascript - vue 数据在异步函数中改变
- python - 使用 os.walk 在目录中移动并执行脚本
- c - 如何识别字符串中第一个单词后的空格?
- reactjs - 即使在rest datagrid的管理员中没有数据显示时也显示标题
- java - java - 如何使用jsp文件中模型的特定列从java arrayList打印值
- java - Android 即时功能:这种方法是否存在根本缺陷?