如果使用SQLAlchemy存在反射列,如何覆盖反射列?

时间:2014-12-04 02:11:27

标签: python sqlalchemy

我在使用SQLAlchemy反映表时要使用的列定义字典,但是如果列实际存在于数据库中,我只想使用每个列定义。例如:

TABLE_DEFAULTS = {
    'my_table': {
        'my_column': Column(String),
        'other_column': Column(String),
        'third_column': Column(String, default='Sample')
    }
}

让我们说我反映my_table,它碰巧有third_columnfourth_column。我有third_column的默认值,所以我想使用它。由于我没有fourth_column的默认值,因此我想使用反射产生的列。以下伪代码显示如何使用默认列生成模型类。

tbl_name = 'my_table'
cls_dict = dict(
    __table_args__={'autoload': True,
                    'autoload_with': engine},
    __tablename__ = tbl_name
)
if tbl_name in TABLE_DEFAULTS:
    # TODO: Only want to add the default columns if they actually exist in db
    cls_dict.update(TABLE_DEFAULTS[tbl_name])

# Unfortunately, MyModel will have attributes for my_column and other_column 
# even though they don't exist
MyModel = type(tbl_name, Base, cls_dict)

为了解决我的问题,我觉得在进行自动加载之前我必须检查数据库,本质上是检查数据库两次。或者可能更好,只是不要自动加载,而是根据早期检查创建列。这是否是这样做的正确方法,还是有更简单的方法?我希望API中的某些内容只有在数据库中存在时才会覆盖列定义。

1 个答案:

答案 0 :(得分:1)

假设每个应用程序只进行一次反射,我没有看到首先检查数据库以获取所需表的列的问题。实际上,您可以使用例程从原始TABLE_DEFAULTS创建更新的字典,其余代码可以无需更改即可生效。

另一种方法是收听column_reflect事件并根据需要修改列。但是在那个阶段,Column实例还没有被创建,相反,该侦听器的column_info参数只是一个属性字典,您可以从原始列覆盖:

{'primary_key': 0, 
 'nullable': False, 
 'default': None, 
 'autoincrement': False,
 'type': VARCHAR(), 
 'name': u'third_column'}