OK, the prefix is on the mapped attribute name, not the column. So
Language(_language = 'foo').
Guess you're looking for the opposite, huh. This gets more weird but this
should work, the main difficulty is limiting the columns being altered to just
those within a certain class hierarchy, if you wanted to do it based on
"table.name.startswith('__')" that would be much simpler:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event
Base = declarative_base()
@event.listens_for(Column, "before_parent_attach")
def attach(col, table, **kw):
if table.name in prefix_tables:
# the trick here is that "col.key" remains
# without the underscore
col.name = "_" + col.name
prefix_tables = set()
class PrefixStuff(object):
# need to use a metaclass here because we have no event
# that will give you the __tablename__ + Language class
# before the Table is actually created
class __metaclass__(type(Base)):
def __init__(self, classname, bases, dict_):
prefix_tables.add(dict_.get('__tablename__'))
if classname == 'PrefixStuff':
return type.__init__(self, classname, bases, dict_)
else:
return type(Base).__init__(self, classname, bases, dict_)
class Language(PrefixStuff, Base):
__tablename__ = 'language'
language_id = Column(Integer, primary_key=True)
language = Column(String(5), unique=True, default='undef')
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
sess = Session(e)
sess.add(Language(language='asdf'))
sess.commit()
On Jun 7, 2013, at 1:40 PM, Richard Gerd Kuesters <[email protected]>
wrote:
> Thank you Mike!
>
> That brings me to another question:
>
> Let's say I have created a simple table (well, I have):
>
> class Language(Base):
> language_id = Column(Integer, Sequence('language_id_seq', optional=True),
> primary_key=True)
> language = Column(String(5), unique=True, default='undef')
>
> The problem is (using pdb):
>
> (Pdb) lang = Language(language='test')
> (Pdb) lang
> <Language(language='test')>
> (Pdb) dir(lang)
> ['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
> '__getattribute__', '__hash__', '__init__', '__mapper__', '__mapper_cls__',
> '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
> '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__table__',
> '__tablename__', '__weakref__', '_cls_id', '_decl_class_registry', '_has',
> '_language', '_language_id', '_sa_class_manager', '_sa_instance_state',
> 'id_', 'language', 'language_id', 'metadata', 't']
> (Pdb) session.add(lang)
> (Pdb) session.commit()
> (Pdb) lang2 = Language(language='foo')
> (Pdb) session.add(lang2)
> (Pdb) session.commit()
> *** IntegrityError: (IntegrityError) column language is not unique u'INSERT
> INTO ht__language (language) VALUES (?)' ('undef',)
> (Pdb) session.rollback()
> (Pdb) session.query(Language).all()
> [<Language(language='test')>]
> (Pdb) lang2 = Language()
> (Pdb) lang2.language = 'foo'
> (Pdb) session.add(lang2)
> (Pdb) session.commit()
> *** IntegrityError: (IntegrityError) column language is not unique u'INSERT
> INTO ht__language (language) VALUES (?)' ('undef',)
> (Pdb) session.rollback()
> (Pdb) lang2 = Language()
> (Pdb) lang2._language = 'foo'
> (Pdb) session.add(lang2)
> (Pdb) session.commit()
> (Pdb) session.query(Language).all()
> [<Language()>, <Language(language='test')>]
>
> If I change the Language class to this:
>
> class Language(Base):
> language_id = Column(Integer, Sequence('language_id_seq', optional=True),
> primary_key=True)
> language = Column('language', String(5), unique=True, default='undef')
>
> The same happens. Curiously:
>
> (Pdb) session.query(Language).all()
> [<Language()>, <Language(language='test')>]
> (Pdb) map(lambda a: a._language, session.query(Language).all())
> [u'foo', u'undef']
>
> Is there a problem using this mapper configuration with declarative bases?
>
> Cheers,
> Richard.
>
>
>
> On 06/07/2013 11:46 AM, Michael Bayer wrote:
>>
>> On Jun 7, 2013, at 9:31 AM, Richard Gerd Kuesters <[email protected]>
>> wrote:
>>
>>> Hi all!
>>>
>>> I'm refactoring a database schema but I need it to mantain reverse
>>> compatibility with older versions of our software - using views.
>>>
>>> But, to avoid confusion to other developers, new tables have two
>>> underscores as a prefix, like:
>>>
>>>
>>> class Base(object):
>>>
>>> @declared_attr
>>> def __tablename__(cls):
>>> return "__%s" % to_python_case(cls.__name__)
>>>
>>>
>>> Now I want to add column prefixes too. I know I can append to this Base
>>> object:
>>>
>>> __mapper_args__ = dict(
>>> column_prefix='_'
>>> )
>>>
>>> But, when I inherit this new base on classes that I need to use
>>> __mapper_args__, column names probably won't have prefixes. Any ideas,
>>> perhaps an event listener to prepend the underscore into *all* column names?
>>
>> one idea is you can intercept how mapper() is called by declarative by
>> overriding __mapper_cls__, like:
>>
>> @classmethod
>> def __mapper_cls__(cls, *args, **kw):
>> kw['column_prefix'] = '_'
>> return mapper(*args, **kw)
>>
>>
>>
>>
>>
>>>
>>>
>>> Cheers,
>>> Richard.
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "sqlalchemy" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an
>>> email to [email protected].
>>> To post to this group, send email to [email protected].
>>> Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.