Classes as model properties

30 views
Skip to first unread message

Tefnet Developers

unread,
Sep 21, 2012, 2:59:31 AM9/21/12
to sqlal...@googlegroups.com
Hi,
we are trying to migrate our old *Extension based SQLA code to new -
event based.
We also have class based properties that we want to keep. With old SQLA
we have had to monkey-patch _as_declarative function to populate our
properties. I wonder if it is possible to avoid doing it with events?
The only close one we found is "mapper_configured", but I'm afraid it is
executed too late. Anyway... I've prepared some short example code. If
you could take a look and advise if/how it can be done...

To check out where is the problem change USE_EVENT value from True to False.
https://gist.github.com/3757273

Regards,
Tomasz Jezierski
Tefnet

Michael Bayer

unread,
Sep 21, 2012, 9:59:03 AM9/21/12
to sqlal...@googlegroups.com
my immediate thought on that code is to replace TefProperty with a function, since you are discarding TefProperty in any case:


def propInt():
return sa.Column(key, Integer)

not sure how the previous Extension version of the code did this differently, this is really a class creational pattern.
> --
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> 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.
>

Tefnet Developers

unread,
Sep 21, 2012, 10:17:11 AM9/21/12
to sqlal...@googlegroups.com
My example is just the shortest code I could come up with to show a
problem, but in production it doesn't look like this.
We're using class inheritance, metaclass features etc, so changing it to
function is not an option for us :|


W dniu 21.09.2012 15:59, Michael Bayer pisze:

Michael Bayer

unread,
Sep 21, 2012, 10:27:00 AM9/21/12
to sqlal...@googlegroups.com


using a class there which replaces itself means you've developed a custom creational pattern. A less hacky approach would be to subclass DeclarativeMeta, and just pass it to your Base:

from sqlalchemy.ext.declarative import DeclarativeMeta

class TefnetMeta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
for key, value in dict_.items():
if isinstance(value, TefProperty):
dict_[key] = value._config(cls, key)
super(TefnetMeta, cls).__init__(classname, bases, dict_)

Base = declarative_base(metaclass=TefnetMeta)

Tefnet Developers

unread,
Sep 21, 2012, 10:57:40 AM9/21/12
to sqlal...@googlegroups.com
In fact we used to use metaclass way of handling this problem, but for
some unknown reason it was changed to monkey patching _as_declarative :|

Couple months ago I've read your post:
http://techspot.zzzeek.org/2011/05/17/magic-a-new-orm/
where there is a similar approach (classes generate relation
properties). I thought that in current SQLA it could be done also with
column properties, but if not it's fine, it's not a big of a deal...
just wanted to know if I can avoid this "hack".

Regards
Tomasz Jezierski
Tefnet

W dniu 21.09.2012 16:27, Michael Bayer pisze:

Michael Bayer

unread,
Sep 21, 2012, 11:19:57 AM9/21/12
to sqlal...@googlegroups.com

On Sep 21, 2012, at 10:57 AM, Tefnet Developers wrote:

> In fact we used to use metaclass way of handling this problem, but for some unknown reason it was changed to monkey patching _as_declarative :|
>
> Couple months ago I've read your post:
> http://techspot.zzzeek.org/2011/05/17/magic-a-new-orm/
> where there is a similar approach (classes generate relation properties). I thought that in current SQLA it could be done also with column properties, but if not it's fine, it's not a big of a deal... just wanted to know if I can avoid this "hack".

you can use that approach, it makes use of the "mapper_configured" event, which for some reason you're saying you can't use.

there's other events to use, but often there are other issues that get in the way when you try to alter mappings within them. You can try "instrument_class": http://docs.sqlalchemy.org/en/rel_0_7/orm/events.html#sqlalchemy.orm.events.MapperEvents.instrument_class

but the fact that my blog post doesn't use it might indicate I hit problems when trying to use that one.

Tefnet Developers

unread,
Sep 21, 2012, 11:31:39 AM9/21/12
to sqlal...@googlegroups.com
W dniu 21.09.2012 17:19, Michael Bayer pisze:
> On Sep 21, 2012, at 10:57 AM, Tefnet Developers wrote:
>
>> In fact we used to use metaclass way of handling this problem, but for some unknown reason it was changed to monkey patching _as_declarative :|
>>
>> Couple months ago I've read your post:
>> http://techspot.zzzeek.org/2011/05/17/magic-a-new-orm/
>> where there is a similar approach (classes generate relation properties). I thought that in current SQLA it could be done also with column properties, but if not it's fine, it's not a big of a deal... just wanted to know if I can avoid this "hack".
> you can use that approach, it makes use of the "mapper_configured" event, which for some reason you're saying you can't use.

I didn't say that I can't use mapper_configured event ... I don't know
how to use it :) Please take a look at:
https://gist.github.com/3757273
With event approach (USE_EVENT=True) I have class properties, I can
construct queries, etc, but table columns are not created.
With old monkey-patching approach (USE_EVENT=False) it works, I have
properties, columns are created, etc...

Michael Bayer

unread,
Sep 21, 2012, 11:58:22 AM9/21/12
to sqlal...@googlegroups.com

On Sep 21, 2012, at 11:31 AM, Tefnet Developers wrote:

> W dniu 21.09.2012 17:19, Michael Bayer pisze:
>> On Sep 21, 2012, at 10:57 AM, Tefnet Developers wrote:
>>
>>> In fact we used to use metaclass way of handling this problem, but for some unknown reason it was changed to monkey patching _as_declarative :|
>>>
>>> Couple months ago I've read your post:
>>> http://techspot.zzzeek.org/2011/05/17/magic-a-new-orm/
>>> where there is a similar approach (classes generate relation properties). I thought that in current SQLA it could be done also with column properties, but if not it's fine, it's not a big of a deal... just wanted to know if I can avoid this "hack".
>> you can use that approach, it makes use of the "mapper_configured" event, which for some reason you're saying you can't use.
>
> I didn't say that I can't use mapper_configured event ... I don't know how to use it :) Please take a look at:
> https://gist.github.com/3757273
> With event approach (USE_EVENT=True) I have class properties, I can construct queries, etc, but table columns are not created.
> With old monkey-patching approach (USE_EVENT=False) it works, I have properties, columns are created, etc...

that particular test fails because the Base.metadata is being used to create the Table objects before the mappers have been configured. the mapper configuration doesn't happen until the mappings are used in some way.

you can force the configuration like this:

from sqlalchemy.orm import compile_mappers
compile_mappers()


add it above the create_all() and the script runs.

Tefnet Developers

unread,
Sep 21, 2012, 1:02:47 PM9/21/12
to sqlal...@googlegroups.com
W dniu 21.09.2012 17:58, Michael Bayer pisze:
> On Sep 21, 2012, at 11:31 AM, Tefnet Developers wrote:
>
>> W dniu 21.09.2012 17:19, Michael Bayer pisze:
>>> On Sep 21, 2012, at 10:57 AM, Tefnet Developers wrote:
>>>
>>>> In fact we used to use metaclass way of handling this problem, but for some unknown reason it was changed to monkey patching _as_declarative :|
>>>>
>>>> Couple months ago I've read your post:
>>>> http://techspot.zzzeek.org/2011/05/17/magic-a-new-orm/
>>>> where there is a similar approach (classes generate relation properties). I thought that in current SQLA it could be done also with column properties, but if not it's fine, it's not a big of a deal... just wanted to know if I can avoid this "hack".
>>> you can use that approach, it makes use of the "mapper_configured" event, which for some reason you're saying you can't use.
>> I didn't say that I can't use mapper_configured event ... I don't know how to use it :) Please take a look at:
>> https://gist.github.com/3757273
>> With event approach (USE_EVENT=True) I have class properties, I can construct queries, etc, but table columns are not created.
>> With old monkey-patching approach (USE_EVENT=False) it works, I have properties, columns are created, etc...
> that particular test fails because the Base.metadata is being used to create the Table objects before the mappers have been configured. the mapper configuration doesn't happen until the mappings are used in some way.
>
> you can force the configuration like this:
>
> from sqlalchemy.orm import compile_mappers
> compile_mappers()
>
>
> add it above the create_all() and the script runs.

Yes, now it looks good. Thank you so much! :)
Reply all
Reply to author
Forward
0 new messages