【问题标题】:Dynamically generated field in SqlAlchemy model with Postgres使用 Postgres 在 SqlAlchemy 模型中动态生成的字段
【发布时间】:2016-11-27 19:20:26
【问题描述】:

我想为浮点类型的一天中的每个小时创建一个包含一列的表。 如何摆脱这种冗长的语法:

from app import db

class HourlySchedule(db.Model):
    id = db.Column(
        db.Integer,
        primary_key=True
    )

    h0 = db.Column(db.Float, nullable=True)
    h1 = db.Column(db.Float, nullable=True)
    h2 = db.Column(db.Float, nullable=True)
    h3 = db.Column(db.Float, nullable=True)
    h4 = db.Column(db.Float, nullable=True)
    h5 = db.Column(db.Float, nullable=True)
    h6 = db.Column(db.Float, nullable=True)
    h7 = db.Column(db.Float, nullable=True)
    h8 = db.Column(db.Float, nullable=True)
    h9 = db.Column(db.Float, nullable=True)
    h10 = db.Column(db.Float, nullable=True)
    h11 = db.Column(db.Float, nullable=True)
    h12 = db.Column(db.Float, nullable=True)
    h13 = db.Column(db.Float, nullable=True)
    h14 = db.Column(db.Float, nullable=True)
    h15 = db.Column(db.Float, nullable=True)
    h16 = db.Column(db.Float, nullable=True)
    h17 = db.Column(db.Float, nullable=True)
    h18 = db.Column(db.Float, nullable=True)
    h19 = db.Column(db.Float, nullable=True)
    h20 = db.Column(db.Float, nullable=True)
    h21 = db.Column(db.Float, nullable=True)
    h22 = db.Column(db.Float, nullable=True)
    h23 = db.Column(db.Float, nullable=True)

另一个问题是如何对值进行检查(例如 0

作为验证?那么我如何巧妙地为 24 个字段设置验证?

我可以改为使用 SqlAlchemy 添加检查约束吗?

【问题讨论】:

  • 如果你真的想在你的表中有 24 列,那么详细的方法没有任何问题。你可以写一个validator 来检查限制。
  • 然后我会发布问题“SqlAlchemy 中动态生成的验证器”

标签: python flask sqlalchemy data-modeling


【解决方案1】:

这里的关键是要意识到class 块只是一个代码块,所以你可以在里面放循环:

class HourlySchedule(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    for i in range(24):
        locals()["h{}".format(i)] = db.Column(db.Float)

    @validates(*("h{}".format(i) for i in range(24)))
    def _validate(self, k, h):
        assert 0 <= h <= 1
        return h

【讨论】:

    【解决方案2】:

    您可能需要调整调用super().__init__(*args, **kwargs) 的顺序,但这理论上应该可行。

    至于验证,validates 装饰器的好处是它需要多个列名,因此我们可以像这样实现动态字段创建和验证:

    from app import db
    from sqlalchemy.orm import validates
    
    
    class HourlySchedule(db.Model):
        id = db.Column(
            db.Integer,
            primary_key=True
        )
    
        def __init__(self, *args, **kwargs):
            self.colstrings = []
    
            for hour in range(0, 24):
                colstring = "h{}".format(hour)
                setattr(self, colstring, db.Column(db.Float, nullable=True))
                self.colstrings.append(colstring)
    
            super().__init__(*args, **kwargs)
    
        @validates(*self.colstrings)
        def validate_hours(self, key, hour): 
            assert 0 < hour < 1
            return hour
    

    不过,我想指出的一点是,这实际上大大增加了一个相当简单的概念的复杂性。与其隐藏模型细节(这意味着冗长以便开发人员可以轻松理解模型 > 表的映射),不如列出每一列,或者重新考虑如何构建数据可能更有意义。

    【讨论】:

      猜你喜欢
      • 2010-11-12
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-30
      相关资源
      最近更新 更多