1

I have a use case where over 190 tables are already mapped using declarative_base.

Occasionally I need to create 'staging' tables for some of these tables. The staging tables' structure differ from the source tables' in that they have 'stage_' prepended to the source table name, and they don't have certain fields.

This is what I came up with after some trial and error.

from sqlalchemy import Table, Column

def MutateDeclarative(source):
    columns = []
    omit_columns = ['created_at', 'updated_at']
    for c in source.__table__.c:
        if c.name not in omit_columns:
            columns.append(((c.name, 
            c.type), 
            {'primary_key': c.primary_key,
            'nullable': c.nullable,
            'doc': c.doc,
            'default': c.default,
            'unique': c.unique,
            'autoincrement': c.autoincrement}))
    class Stage(Base):
        __tablename__ = 'stage_' + source.__tablename__    
        __table__ = Table('stage_' + source.__tablename__, 
            Base.metadata, *[Column(*c[0], **c[1]) for c in columns])
    return Stage

And this code works. I can call it as such

from models import Customer
MutatedCustomer = MutateDeclarative(Customer)

But I don't really know what I did there, just that it works. Could there be any unintended consequence arising from this usage, or is there a standard way to generate a class from another declarative class with the only change being a change in the table name and the omission of some columns.

Many Thanks to the community for explaining this.

Haleemur Ali
  • 26,718
  • 5
  • 61
  • 85

1 Answers1

0

I don't know exactly what your intentions were, so I can't tell whether there are unintended consequences. However this looks completely OK to me. You just create a new class for each call of MutateDeclarative().

If you stumble upon any problems ("unintended consequences"), you'd just have to extend your MutateDeclarative() to deal with it, too.

It feels a bit like prototype-based inheritance in python.

knitti
  • 6,817
  • 31
  • 42