在SQLAlchemy中从字典创建表

时间:2017-07-05 23:39:03

标签: python python-3.x flask sqlalchemy flask-sqlalchemy

我正在尝试从SQLAlchemy中的字典值创建一个表。我正在使用Flask,目前我的班级看起来像这样:

class Machine(db.Model):
    """Template for the Machine Info table"""
    __tablename__ = 'machine'
    id = db.Column(db.Integer, primary_key=True)
    machine_name = db.Column(db.String(32))
    date = db.Column(db.String(32))
    time = db.Column(db.String(32))
    sensor1 = db.Column(db.String(32))
    sensor2 = db.Column(db.String(32))

这很好用,但我的问题是我最终会在这个表中有很多列,可能是+100。我宁愿不填写我的models.py文件,包含100行这类东西。我希望将它放在自己的字典中,在自己的文件中,字典看起来像这样:

SENSOR_LOOKUP_DICT = {
    "machine_name":"machine_name",
    "date":"date",
    "time":"time",
    "sensor1":"sensor1",
    "sensor2":"sensor2"
}

列表可能也适用于此。

我在想我可以使用某种循环,如下所示:

class Machine(db.Model):
    """Template for the Machine Info table"""
    __tablename__ = 'machine'
    id = db.Column(db.Integer, primary_key=True)
    for sensor in SENSOR_LOOKUP_DICT:
        sensor = db.Column(db.String(32))

但这只是给我一个名为传感器的专栏。我在sqlalchemy中找到了几个相关的问题,但他们没有使用这种结构来创建表格。我非常喜欢一个方法,如果可能的话,继续使用db.Model结构,而不是使用create_engine的结构,因为稍后的一些JSON序列化对于这种结构更容易(以及一些应用程序结构的东西)。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:1)

您可以将设计拆分为机器和传感器表,而不是将所有传感器值填入a single row of hundred or more columns

from datetime import datetime

from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy

class Machine(db.Model):
    """The Machine Info table"""
    __tablename__ = 'machine'
    id = db.Column(db.Integer, primary_key=True)
    machine_name = db.Column(db.String(32))
    datetime = db.Column(db.DateTime, default=datetime.utcnow)
    sensors = db.relationship(
        'Sensor',
        collection_class=attribute_mapped_collection('name'),
        cascade='all, delete-orphan')
    sensor_values = association_proxy(
        'sensors', 'value',
        creator=lambda k, v: Sensor(name=k, value=v))

class Sensor(db.Model):
    """The Sensor table"""
    __tablename__ = 'sensor'
    machine_id = db.Column(db.Integer, db.ForeignKey('machine.id'),
                           primary_key=True)
    # Note that this could be a numeric ID as well
    name = db.Column(db.String(16), primary_key=True)
    value = db.Column(db.String(32))

dictionary collection relationshipassociation proxy结合使您可以像这样处理传感器值:

In [10]: m = Machine(machine_name='Steam Machine')

In [11]: m.sensor_values['sensor1'] = 'some interesting value'

In [12]: db.session.add(m)

In [13]: db.session.commit()

In [14]: m.sensor_values
Out[14]: {'sensor1': 'some interesting value'}

In [16]: m.sensor_values['sensor1']
Out[16]: 'some interesting value'

使用单独的表而不是固定模式的另一个好处是,如果您在生命中稍后添加传感器,则无需迁移模式以适应这种情况 - 换句话说,无需更改表以添加列。只需像以前一样将新的传感器值添加到传感器表中。

最后,一些RDBMS支持不同类型的文档类型,例如您可以使用的Postgresql的hstore,json和jsonb列,因为传感器表本质上是一个键/值存储。