Woah, I may have wondered that when I thought on attaching an event, but yes I was thinking the opposite when using it like the underscores in the table name level.

I can't see how this was easier - lol - but it makes sense to me :)

Thanks Mike! This should get into the SA examples or recipes!

Best regards,
Richard.

On 06/07/2013 03:13 PM, Michael Bayer wrote:
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] <mailto:[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] <mailto:[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] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[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] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[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.


Reply via email to