9

I know there is a way to instrument SQLAlchemy to prepend common prefix to all columns, is it possible to add a common prefix to all table names derived from single declarative_base?

canni
  • 5,737
  • 9
  • 46
  • 68

1 Answers1

9

Use declared_attr and a customized Base along the lines of:

from sqlalchemy.ext.declarative import declared_attr

class PrefixerBase(Base):

    __abstract__ = True

    _the_prefix = 'someprefix_'

    @declared_attr
    def __tablename__(cls):
        return cls._the_prefix + cls.__incomplete_tablename__


class SomeModel(PrefixerBase):

    __incomplete_tablename__ = 'sometable'
    ...

A class marked with __abstract__ will not get a table or mapper created and can act as the extended declarative base.

You could also make it even more implicit using a custom metaclass (originally described here):

from sqlalchemy.ext.declarative.api import DeclarativeMeta


class PrefixerMeta(DeclarativeMeta):

    def __init__(cls, name, bases, dict_):
        if '__tablename__' in dict_:
            cls.__tablename__ = dict_['__tablename__'] = \
                'someprefix_' + dict_['__tablename__']

        return super().__init__(name, bases, dict_)

Base = declarative_base(metaclass=PrefixerMeta)


class SomeModel(Base):

    __tablename__ = 'sometable'
    ...
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
  • I've tried the ``@declared_attr`` approach, but it breaks when Single-Table-Inheritance is used, I'll try the metaclass through – canni Jul 07 '16 at 12:51
  • Also, unfortunately as far as I understand this won't work with ``M2M`` join tables, witch if not explicit don't inherit fro declarative base – canni Jul 07 '16 at 12:54
  • No, it would not work for manual `Table`s, as they have nothing to do with declarative. For those consider using a wrapper function or such. – Ilja Everilä Jul 07 '16 at 12:58
  • I'll just make them as a subclass of `declarative`` easy enough, thanks for that – canni Jul 07 '16 at 13:00
  • Btw how does `@declared_attr` break with single table inheritance? Asking out of sheer interest. – Ilja Everilä Jul 07 '16 at 13:01
  • 1
    It converts it to Joined Table Inheritance, by declaring ``__tablename__`` attribute on a subclass (You can use ``@declared_attr.cascading`` and somehow detect that STI, but I don't know how :) ) – canni Jul 07 '16 at 13:07