Dynamically declaring the property name of a column

58 views
Skip to first unread message

John Anderson

unread,
Nov 6, 2012, 5:42:17 PM11/6/12
to sqlal...@googlegroups.com
I have a mixin that declares a primary key but would like to dynamically override the name of it.

So for instance this is the base:

class BaseModel(object):
    @declared_attr
    def pk(self):
        return sa.Column(sa.Integer, autoincrement=True, primary_key=True)

but in some circumstances people want to use my mixin but declare the primary key property as id instead.

So I want to be able to do something class

class SubClass(BaseModel):
    _idAttribute = 'id'

and have it use id in the database and has the class property to reference instead of pk.


Is this possible?

Michael Bayer

unread,
Nov 6, 2012, 5:58:46 PM11/6/12
to sqlal...@googlegroups.com
The name assigned to the class and the name given to the Column when it emits CREATE TABLE are two different things.

The "name" is what you'll see in CREATE TABLE, easy enough, "return Column('id', ...)"

As far as the name assigned to the class, in classical mappings the "key" of the Column is used, and it might be nice if declarative looked at column.key in this case, however it doesn't. There is a way this could probably be hacked on, by creating a custom __mapper__ classmethod and converting all the Columns with custom .keys to be mapped with that name. a little ugly, though.

of course the blunt tool that works in all cases is the custom metaclass, but that approach is fairly tedious and is probably a lot uglier than just the __mapper__ hack above.

Another way that is a little verbose but is the least intrusive is to just use more @declared_attrs.

in 0.8, @declared_attr can be specified on a non-mixin, so this works there:

class A(BaseModel, Base):
__tablename__ = "a"

@declared_attr
def pk(self):
return None

@declared_attr
def id(self):
return BaseModel.pk

if 0.7, another mixin can do it:

class SubBaseModel(BaseModel):
@declared_attr
def pk(self):
return None

@declared_attr
def id(self):
return BaseModel.pk

class A(SubBaseModel, Base):
__tablename__ = "a"

i can show you the __mapper__ hack if that's not good enough.



John Anderson

unread,
Nov 6, 2012, 6:39:30 PM11/6/12
to sqlal...@googlegroups.com
I'm using 0.8 but the library itself is open source so it might be good to support older versions.   Does the 0.7 version work for both?   Or is the mapper hack the best way for backwards compatibility?

Michael Bayer

unread,
Nov 6, 2012, 7:18:52 PM11/6/12
to sqlal...@googlegroups.com
the two declared_attr approach on the mixin is fine for both.


--
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/d0v7hdxF9FMJ.
To post to this group, send email to sqlal...@googlegroups.com.
To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.

Reply all
Reply to author
Forward
0 new messages