On 5/13/15 5:33 PM, Bruno Grande wrote:
I was looking for a way of typecasting attributes that are mapped to Integer columns as Python integers without having to commit to the database first. On the IRC channel, I was pointed towards simple validators and the @validates decorator. While this works, implementing validation using this approach for all integer attributes across all classes seems inefficient.

I then looked into AttributeEvents with the idea of adding a listener to the base class, but I can't seem to figure out a way for have the listener listen to all attribute changes. The documentation <http://docs.sqlalchemy.org/en/latest/orm/events.html#sqlalchemy.orm.events.AttributeEvents.set> only gives examples for listening to specific attributes (see example code below pulled from documentation).

|
from sqlalchemy import event

@event.listens_for(SomeClass.some_attribute, 'set')
def receive_set(target, value, oldvalue, initiator):
    # ... (event handling logic) ...
|

Hence, I was wondering if any of you would have a clever and straightforward way of achieving type validation on all classes (at least for integers for now). Thanks!

*Extra Information*
Python 2.7.8
SQLAlchemy 0.9.8

So first off, in Python we do have the option of overriding a builtin method called __setattr__(), which if you really wanted to intercept most attribute set events, you could just do that. This is heavy-handed though because it is called for all attribute sets everywhere and it would spend a lot of time filtering out attributes it doesn't care about.

Secondly, @validates and AttributeEvents are two versions of the same thing - @validates is a shortcut for AttributeEvents, and the AttributeEvents listener is set up on a per-attribute basis. So there's not too much difference except how these are configured, and using the AttributeEvents is better for programmatic attachment. You can also set up such a listener for all mapped attributes everywhere, but again this is too broad and such a listener again wastes lots of time filtering on which events it cares about.

With that information out of the way, the general strategy to listen to events on things that are mapped such that the things which we're listening to is also dynamic / programmatic is to apply event listeners to the attributes we care about. There's more events that we make use of in order to set up event listeners at the moment that these various attributes and other things are mapped. There are a lot of ways to catch such events, but the most easy one that was added mostly for this purpose is known as the "attribute_instrument" event, which is called whenever a new class attribute becomes part of a SQLAlchemy mapping. This is a good place where you can check how this attribute is mapped and make decisions about what kind of validation it should have. Two examples are provided, one which illustrates how to apply a listener to all the events associated with a base class, that is at http://docs.sqlalchemy.org/en/rel_1_0/_modules/examples/custom_attributes/listen_for_events.html, and there's also a recipe which I think is nicer that sets up validators based on the column types, such as your Integer here, that is at https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/ValidateOnType.




Best regards,
Bruno
--
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.
For more options, visit https://groups.google.com/d/optout.

--
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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to