【问题标题】:Override default in sqlalchemy reflected tables覆盖 sqlalchemy 反射表中的默认值
【发布时间】:2010-10-30 16:57:42
【问题描述】:

我已经反映了现有 mysql 数据库中的大量表。我想表达的是,任何表中具有特定名称的任何列都默认为 datetime.now()。然而,天真地循环遍历表和列,只是在我发现有特定名称的那些上设置默认值是行不通的,当做 session.add(); session.flush() 我得到以下错误:

AttributeError: 'builtin_function_or_method' object has no attribute '__visit_name__'

这似乎与对 _set_parent 的调用有关(以及 sqlalchemy.schema 中第 721 行的 this self._init_items(*toinit)。

有谁知道是否有一种方法可以做到这一点,而无需遍历我所有的反射表并在每个地方都添加 Column(..) 行都做同样的事情或诉诸非常丑陋的黑客行为?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    另一种选择是在反射时覆盖需要默认值的列:

    Table('some_table', metadata,
        Column('create_time', DateTime, default=datetime.now),
        autoload=True)
    

    不幸的是,您目前无法反映数据类型并同时设置 SQLAlchemy 端默认值。有人可能会争辩说,数据类型是接口定义的一部分,因此冗余不会造成维护问题 - 如果列数据类型发生更改,您很可能也需要更改默认值函数。

    【讨论】:

    • 感谢 Ants,这绝对是我在每个表基础上的首选方法,但是我一次反映了多个表,我希望一个规则适用于具有此特定列名的所有表,所以我在下面将我的答案标记为首选(如果 icky)答案。
    【解决方案2】:

    好的,我已经解决了这个问题,这是一个相当可怕的黑客攻击,因为我使用了内部方法。你需要做的:

    from sqlalchemy.schema import ColumnDefault
    #....
    ColumnDefault(callable)._set_parent(column)
    

    这会产生所需的行为。请注意,您也可以将 ColumnDefault 传递给 kwarg for_update=True,这将改变行为以在 UPDATE 而不是插入时改变。

    我觉得很脏:-(

    【讨论】:

      【解决方案3】:

      五年后,您可以使用事件侦听器[1]。您可以使用要运行的函数注册侦听器:

      def do_this_on_column_reflect(inspector, table, column_info):
          column_name = column_info.get("name")
          if column_name == "create_datetime":
              column_info["default"] = datetime.now()
      event.listen(Table, "column_reflect", do_this_on_column_reflect)
      

      [1]http://docs.sqlalchemy.org/en/latest/core/events.html#sqlalchemy.events.DDLEvents.column_reflect [2]http://docs.sqlalchemy.org/en/latest/core/event.html#sqlalchemy.event.listen

      【讨论】:

        猜你喜欢
        • 2012-08-31
        • 2011-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-08
        • 1970-01-01
        相关资源
        最近更新 更多