Skip to content Skip to sidebar Skip to footer

Sqlalchemy Reflection Using Metaclass With Column Override

I have a set of dynamic database tables (Postgres 9.3 with PostGIS) that I am mapping using a python metaclass: cls = type(str(tablename), (db.Model,), {'__tablename__':tablename})

Solution 1:

I'm not sure if I exactly follow what you're doing, but I've overridden reflected columns in the past inside my own __init__ method on a custom metaclass that inherits from DeclarativeMeta. Any time the new base class is used, it checks for a 'wkb_geometry' column name, and replaces it with (a copy of) the one you created.

import sqlalchemy as sa
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base

wkb_geometry = db.Column(Geometry("POLYGON"))

classMyMeta(DeclarativeMeta):
    def__init__(cls, clsname, parents, dct):
        for key, val in dct.iteritems():
            ifisinstance(sa.Column) and key is'wkb_geometry':
                dct[key] = wkb_geometry.copy()

MyBase = declarative_base(metaclass=MyMeta)

cls = type(str(tablename), (MyBase,), {'__tablename__':tablename})

This may not exactly work for you, but it's an idea. You probably need to add db.Model to the MyBase tuple, for example.

Solution 2:

This is what I use to customize a particular column while relying on autoload for everything else. The code below assumes an existing declarative Base object for a table named my_table. It loads the metadata for all columns but overrides the definition of a column named polygon:

classMyTable(Base):
    __tablename__ = 'my_table'
    __table_args__ = (Column(name='polygon', type=Geometry("POLYGON"),
                      {'autoload':True})

Other arguments to the Table constructor can be provided in the dictionary. Note that the dictionary must appear last in the list!

The SQLAlchemy documentation Using a Hybrid Approach with __table__ provides more details and examples.

Post a Comment for "Sqlalchemy Reflection Using Metaclass With Column Override"