首页 文章

在SQLAlchemy中从字典创建表

提问于
浏览
0

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

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 回答

  • 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列,因为传感器表本质上是键/值存储 .

相关问题