On Aug 26, 2013, at 4:35 PM, Praveen <praveen.venk...@gmail.com> wrote:

> The problem with using Mixins is that you need to know the definition of 
> columns already for creating the mixin class. What I am trying to do is more 
> like get the definition dynamically on the fly.Take a look at this:

here's a simple way to add reflection events which intercept the Column and add 
the .key of your choice, and saves on code by making use of the existing 
DeferredReflection mixin instead of hand-coding it.  There's many more variants 
on this kind of thing as well.   DeferredReflection is using some 
not-yet-public APIs to do its work, but there are other ways of deferring the 
mapping as well (typically by overriding the __mapper__ attribute).   Basically 
your class creates itself an empty Table object, to which we apply events.  
then DeferredReflection.prepare() fills in those Table objects with their 
columns using reflection.

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import DeferredReflection
from sqlalchemy import event

Base = declarative_base()

e = create_engine("sqlite://", echo=True)
e.execute("""
    create table sample (
        Id integer primary key,
        Name varchar,
        Description varchar,
        IsActive varchar
    )
""")

class MagicMappyThing(DeferredReflection):
    @classmethod
    def __declare_last__(cls):
        @event.listens_for(cls.__table__, "column_reflect")
        def new_col(inspector, table, column_info):
            column_info['key'] = cls.__map__.get(column_info['name'], 
column_info['name'])

class Sample(MagicMappyThing, Base):
    __tablename__ = 'sample'
    __map__ = {'Id': 'id', 'Name': 'name', 'Description': 'description', 
'IsActive': 'is_active'}

    def __init__(self, id, name, description, is_active):
        self.id = id
        self.name = name
        self.description = description
        self.is_active = is_active

MagicMappyThing.prepare(e)

s = Session(e)

s.add(Sample(id=1, name='some name', description='foo', is_active='foo'))
s.commit()






> 
> def get_properties(tablename, map):
>     table_inspector = reflection.Inspector.from_engine(DB_ENGINE.connect())
>     table = Table(tablename, metadata)
>     table_inspector.reflecttable(table, None)
>     columns = []
>     for child in table.get_children():
>         if isinstance(child, Column):
>             column = list(child.base_columns)[0]
>             column.table = None
>             columns.append(column)
>     return dict([(map[column.key],  column) for column in columns])
> 
> class CustomDeclarativeMeta(DeclarativeMeta):
>     def __new__(cls, name, bases, attrs):
>         attrs.update(get_properties(attrs.get('__tablename__'), 
> attrs.get('__map__')))
>         return super(CustomDeclarativeMeta, cls).__new__(cls, name, bases, 
> attrs)
> 
> # Base = declarative_base(metaclass=CustomDeclarativeMeta)
> Base = declarative_base()
> 
> class Enum_SampleBase):
>     __tablename__ = 'Enum_Sample'
>     __table_args__ = {'useexisting': True}
>     __metaclass__ = CustomDeclarativeMeta
>     __map__ = {'Id': 'id', 'Name': 'name', 'Description': 'description', 
> 'IsActive': 'is_active'}
> 
>     def __init__(self, id, name, description, is_active):
>         self.id = id
>         self.name = name
>         self.description = description
>         self.is_active = is_active
> 
>     def __repr__(self):
>         return "<(%d, '%s', '%s', %r)>" % (self.id, self.name, 
> self.description, self.isactive)
> 
> Unfortunately, this isn't working. I want to declare column types by getting 
> them from a table that's already created in the database.
> 
> 
> 
> On Wed, Jul 3, 2013 at 11:11 AM, Michael Bayer <mike...@zzzcomputing.com> 
> wrote:
> your metaclass must derive from the DeclarativeMeta class.
> 
> Also, I disagree that you need this metaclass,  what you're trying to do is 
> very easy using mixins, which are supported in version 0.6: 
> http://docs.sqlalchemy.org/en/rel_0_6/orm/extensions/declarative.html#mixing-in-columns
> 
> 
> 
> 
> On Jul 3, 2013, at 12:44 AM, Ven Karri <praveen.venk...@gmail.com> wrote:
> 
>> I use: Python 2.6 and sqlalchemy 0.6.1
>> 
>> This is what I am trying to do:
>> 
>>      from sqlalchemy.types import (
>>          Integer,
>>          String,
>>          Boolean
>>      )
>>      from sqlalchemy.ext.declarative import declarative_base
>> 
>>     Base = declarative_base()
>> 
>>      class SampleMeta(type):
>>         def __new__(cls, name, bases, attrs):
>>             attrs.update({   'id': Column('Id', Integer, primary_key=True),
>>                         'name': Column('Name', String),
>>                         'description': Column('Description', String),
>>                         'is_active': Column('IsActive', Boolean)
>>                     })
>>             return super(SampleMeta, cls).__new__(cls, name, bases, attrs)
>> 
>>     class Sample(Base):
>>         __tablename__ = 'Sample'
>>         __table_args__ = {'useexisting': True}
>>         __metaclass__ = SampleMeta
>> 
>>         def __init__(self, id, name, description, is_active):
>>             self.id = id
>>             self.name = name
>>             self.description = description
>>             self.is_active = is_active
>> 
>>         def __repr__(self):
>>             return "<(%d, '%s', '%s', %r)>" % (self.id, self.name, 
>> self.description, self.isactive)
>> 
>> And the error I am getting is this:
>> 
>>     TypeError: Error when calling the metaclass bases
>>         metaclass conflict: the metaclass of a derived class must be a 
>> (non-strict) subclass of the metaclasses of all its bases
>> 
>> Now, if I do the same thing above by using
>> 
>>     class Sample(object)
>> 
>> instead of
>> 
>>     class Sample(Base)
>> 
>> it works absolutely fine.
>> 
>> I need to update the attributes of the class dynamically. So, I will be 
>> using dynamic attribute and column names. And I need the above piece code to 
>> work in order to be able to get there.
>> 
>> **Please help** 
>> 
>> -- 
>> 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 sqlalchemy+unsubscr...@googlegroups.com.
>> 
>> To post to this group, send email to sqlalchemy@googlegroups.com.
>> Visit this group at http://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>  
>>  
> 
> 
> -- 
> You received this message because you are subscribed to a topic in the Google 
> Groups "sqlalchemy" group.
> To unsubscribe from this topic, visit 
> https://groups.google.com/d/topic/sqlalchemy/37M-1Qf8HO8/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.
>  
>  
> 
> 
> 
> -- 
> Have a nice day !!!
> 
> -- 
> 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 sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to