【问题标题】:Model Creation by SQLAlchemy database reflection通过 SQLAlchemy 数据库反射创建模型
【发布时间】:2011-11-14 13:09:56
【问题描述】:

我目前正在研究一个使用 sqlalchemy 的金字塔系统。

该系统将包含一个模型(我们称之为 Base),该模型存储在 数据库表。该模型应该可以由用户在运行时进行扩展。基本上,用户 应该能够对 Base 进行子类化并创建一个新模型(我们称其为“Child”)。 孩子应该存储在另一个数据库表中。

所有可用的示例似乎都处理预定义模型上的数据库反射。 通过数据库反射生成完整模型类的最佳方法是什么?

【问题讨论】:

    标签: python reflection sqlalchemy pyramid


    【解决方案1】:

    这似乎与“数据库反射”没有太大关系,而是动态表创建。这是一项非常危险的操作,通常不受欢迎。

    您应该尝试考虑如何为您的用户希望添加到 Base 的可能结构建模,并围绕它设计您的架构。有时,当您不知道列可能是什么时,这些灵活的结构可以从垂直表格中受益匪浅。

    不要忘记,有一整类数据存储系统可以为“无模式”模型提供更灵活的支持。像 Mongo 或 ZODB 这样的东西在这里可能更有意义。

    【讨论】:

      【解决方案2】:

      这个概念的大部分对我来说都很好,但是我无法将现有表绑定到新创建的类,该类使用多表继承。这里有一些代码可以让事情更清楚:

      Base.metadata.reflect(bind=Session.bind)
      table = Base.metadata.tables['anExistingTable']
      Extension = type('Extension', (BaseClass,), {})
      orm.mapper(Extension, table, inherits=orm.class_mapper(BaseClass),
          polymorphic_identity='extension')
      

      这会导致以下错误:

      ArgumentError: Class '<class 'Extension'>' already has a primary mapper defined. Use non_primary=True to create a non primary Mapper. clear_mappers() will remove *all* current mappers from all classes.
      

      您知道为什么在刚刚创建的类上定义了主映射器吗?

      【讨论】:

        【解决方案3】:

        我刚刚通过使用以下代码sn-p解决了上述问题:

        table = Table('anExistingTable', Base.metadata, autoload=True, autoload_with=Session.bind)
        Extension = type('Extension', (BaseClass,), {
            '__table__' : table,
            '__mapper_args__' : {
                'inherits': BaseClass,
                'polymorphic_identity': 'extension'
            }
        })
        

        但是,我不知道为什么第一次尝试没有成功...

        【讨论】:

          【解决方案4】:

          只需定义一个生成器方法

          def mapClass(class_name, table_name):
              # Allows to generate previously undefined mapped classes, remapping when necessary
              #For security reason this will only map a class 
              #when class is not previously declared
              #or if declared, when is a MappableClass subclass, 
              #this way we prevent to map any class.
              #Even when not able to return a mapped class it will return corresponding class_name class
              #if so, we'll get an error when accessing non existing MappableClass members
              if not globals.has_key(class_name):
                  cls=type(class_name, (MappableClass,), {} )
                  globals[class_name]=cls
              else:
                  cls=globals[class_name]
              if issubclass(cls,MappableClass):
                  tab_obj=Table(table_name,meta,autoload=True)
                  mapper(cls, tab_obj)
              return cls
          

          或者继承一个生成器类为here 我在答案的类中将生成器方法添加为静态,因此我可以使用先前声明的子类或新的动态创建的子类。

          【讨论】:

          • 您好,谢谢您的回答。但是你知道如何将多表继承的概念(见下文)融入其中吗?
          • 嗯……不知道sqlalchemy是怎么处理表继承的……是不是把继承信息存到​​数据库里了? (抱歉问而不是回答)如果没有,您需要存储它并在类生成时检索它。无论如何,您可以将继承映射器参数添加到 mapClass 方法
          • 是的,多态类型存储在数据库中(see here)。但是我很难找到数据库反射和继承相结合的解决方案。
          • 我不是 sqlalchemy 专家,但您能简单介绍一下您需要做什么吗?
          • 我刚刚解决了这个问题,并在下面发布了我的解决方案。不过感谢您的帮助:)
          猜你喜欢
          • 2015-02-06
          • 2018-11-27
          • 2011-03-02
          • 2022-12-07
          • 1970-01-01
          • 2014-06-19
          • 2014-04-08
          • 1970-01-01
          • 2017-02-25
          相关资源
          最近更新 更多