@validates is a decorator that's typically associated with a class before it's 
mapped.   It is essentially a mapper-time directive which is converted into an 
attribute event.

If you're trying to associate these events with class attributes en-masse, and 
particularly that may already be mapped, you'd want to use the event API 
directly and establish attribute events:


        from sqlalchemy import event

        def create_validator(cls):
                def validate(target, value, oldvalue, initiator):
                    if not cls._type_[name].validate(value):
                        raise ValueError("incorrect value '%s' for '%s' in 
'%s'" % (str(value), name, cls.__name__))
                    # note no return value is needed by default
                return validate

        def create_validators(self):      
            for cls in self.itervalues():
                for fld in cls._type_.fields():
                    attribute = getattr(cls, fld.key())
                    event.listen(attribute, "set", create_validator(cls))


note also that in your original code, the "def validator()" will not refer to 
the correct value of "cls" in most cases as the "cls" name changes due to the 
loop.   Hence the need for the create_validator() call.


On Jan 4, 2013, at 7:11 AM, lars van gemerden wrote:

> Hi,
> 
> I am trying to use validates() to dynamically add validation to my sqla 
> classes, but i cannot figure out how to do this. I have read python decorator 
> docs and docs n validates, but something escapes me (or it is just not 
> possible).
> 
> A code snippet (this does not work):
> 
>     def create_validators(self):      
>         for cls in self.itervalues():
>             names = tuple([fld.key() for fld in cls._type_.fields()])
>             def validator(obj, name, value):
>                 if not cls._type_[name].validate(value):
>                     raise ValueError("incorrect value '%s' for '%s' in '%s'" 
> % (str(value), name, cls.__name__))
>                 return value
>             setattr(cls, 'validator', validates(*names)(validator)) #does NOT 
> work
> 
> in which:
> 
> 'self' is a dictionary of sqla classes, 
> 'cls' is an sqla class (derived from declarative_base(...)), 
> 'cls._type_' contains the information for (further) generation of 'cls' (e.g. 
> cls._type_[name].validate(value) calls a validate method for value for a 
> field (say String(50)) with name 'name')
> 
> The method above runs without problem, but the validator function is never 
> called when setting field values. I have tried all alternatives i can think 
> of, but maybe i am missing something basic.
> 
> Can anyone help?
> 
> Cheers, Lars
> 
> 
> 
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To view this discussion on the web visit 
> https://groups.google.com/d/msg/sqlalchemy/-/-F7Lqaw1AagJ.
> To post to this group, send email to sqlalchemy@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 sqlalchemy@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