Reputation: 12672
I have a dictionary of column definitions that I want to use when reflecting a table using SQLAlchemy, but I only want to use each column definition if the column actually exists in the database. For example:
TABLE_DEFAULTS = {
'my_table': {
'my_column': Column(String),
'other_column': Column(String),
'third_column': Column(String, default='Sample')
}
}
Let's say I'm reflecting my_table
and it happens to have third_column
and fourth_column
. I have a default for third_column
, so I'd like to use that. Since I have no default for fourth_column
, I'd like to use the Column resulting from the reflection. The following pseudocode displays how the default columns are used to generate the model class.
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)
To solve my problem, I feel like I have to inspect the database before doing the autoload, essentially inspecting the database twice. Or probably better, just don't autoload, and instead create the columns based off of the earlier inspection. Would this be the proper way to do this, or is there a simpler way? I was hoping maybe there would be something in the API to override column definitions only if they exist in the database.
Upvotes: 0
Views: 598
Reputation: 76992
Assuming that reflection is done only once per application, I do not see a problem inspecting first the database only to get columns for the required tables. In fact, you can have a routine to create an updated dictionary from your original TABLE_DEFAULTS
and the rest of your code would work without changes.
An alternative would be to listen to column_reflect
event and modify the column as required there. But at that stage the Column
instances are not created yet, and instead the column_info
parameter to that listener is simply a dictionary of attributes, which you can overwrite from your original columns:
{'primary_key': 0,
'nullable': False,
'default': None,
'autoincrement': False,
'type': VARCHAR(),
'name': u'third_column'}
Upvotes: 1