Declarative classes should default to __tablename__ = classname

Issue #1270 resolved
Former user created an issue

A current workaround is something like:

class Defaults( DeclarativeMeta ):        
    def __init__( cls, classname, bases, dict_ ):
        if not hasattr( cls, "__tablename__" ):
            cls.__tablename__ = classname
        return DeclarativeMeta.__init__( cls, classname, bases, dict_ )

Base = declarative_base( metadata = metadata, metaclass = Defaults )

class Cover( Base ):
    #~ __tablename__ = 'Cover'
    id        = Column( Integer, primary_key = True )
    title     = Column( Text )

i.e. The default class makes specifying !tablename! unnecessary.

At the moment if a !tablename! is not specified, a confusing error message is given:

sqlalchemy.exc.ArgumentError: Mapper 'Mapper|Cover|None' does not have a mapped_table specified.  (Are you using the return value of table.create()?  It no longer has a return value.)

Comments (4)

  1. Mike Bayer repo owner

    Take the code you've put there, and add it to UsageRecipes. SQLA doesn't do any kind of derived naming stuff (with the exception of index=True on Column, which I'm not thrilled about). For example, I'd never name a table Cover (or any kind of CamelCase name) - the case sensitive name would be quoted all the time and be painful to use...so already, our disagreement on naming preference becomes a non-issue by keeping this as a usage recipe.

    It's true that we do some implicit naming in declarative when we say id = Column(Integer), but that's really just the "reverse" of the fact that SQLA names the mapped attributes the same as the existing column. We don't have a corresponding make_me_a_class(Table("Cover")) which magically places a class called Cover in the global namespace.

  2. Former user Account Deleted

    zzzeek, thanks for your detailed response, which makes perfect sense. Much appreciated.

  3. Log in to comment