On Sep 22, 2010, at 4:30 AM, Yap Sok Ann wrote:

> This is related to topic "need 0.6_beta2-compat declarative meta"
> http://groups.google.com/group/sqlalchemy/browse_thread/thread/ae7cb9d2ab0b9cca
> 
> Prior to version 0.6, I use the following code to automatically add a
> primary key if the table doesn't have one defined:
> 
> from sqlalchemy.ext.declarative import declarative_base,
> DeclarativeMeta
> from sqlalchemy.schema import Column
> from sqlalchemy.types import Integer
> 
> class Meta(DeclarativeMeta):
>    def __init__(cls, classname, bases, dict_):
>        for attr in dict_.itervalues():
>            if isinstance(attr, Column) and attr.primary_key:
>                break
>        else:
>            dict_['id'] = Column(Integer, primary_key=True)
>        return super(Meta, cls).__init__(classname, bases, dict_)
> 
> Base = declarative_base(metaclass=Meta)
> 
> Of course, that doesn't work anymore in 0.6. The suggestion from the
> aforementioned threads is to replace:
> 
> dict_['id'] = Column(Integer, primary_key=True)
> 
> with
> 
> cls.id = Column(Integer, primary_key=True)
> 
> Unfortunately, that alone doesn't work in this case. The problem is
> that the Base class itself will be the first one to go through the
> Meta.__init__() method, so the whole thing essentially becomes:
> 
> Base.id = Column(Integer, primary_key=True)
> 
> For it to work, I have to wrap the code in an if-block, i.e.
> 
> class Meta(DeclarativeMeta):
>    def __init__(cls, classname, bases, dict_):
>        if classname != 'Base':
>            for attr in dict_.itervalues():
>                if isinstance(attr, Column) and attr.primary_key:
>                    break
>            else:
>                cls.id = Column(Integer, primary_key=True)
>        return super(Meta, cls).__init__(classname, bases, dict_)
> 
> which looks rather ugly. Is there a cleaner way to achieve this?

I didn't think metaclasses were supposed to be pretty ?    Checking that you're 
not "the base" is pretty standard metaclass stuff.      If the hardcoded name 
is the issue, you can look in bases:

        if object not in bases:
 
or something more generic:

        for k in cls.__mro__[1:]:
            if isinstance(k, Meta):
                # you're a Base subclass



> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@googlegroups.com.
> To unsubscribe from this group, send email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to