stevearc / flywheel

Object mapper for Amazon's DynamoDB
MIT License
128 stars 25 forks source link

Adding validators to fields #17

Closed mortaliorchard closed 10 years ago

mortaliorchard commented 10 years ago

More of an enhancement: it would be great if there was a way to define more than just the type of the field, but also few additional rules.

Example (found on the SQLAlchemy documentation):

username = Column(String(18))
numberoverzero commented 10 years ago

Adding validators might be easier if Fields were implemented as Descriptors. Right now Models implement __getattribute__ and __setattribute to handle watching field changes, which is where that logic would probably live (or I guess, Field.resolve).

Using Descriptors would make it pretty easy to drop validation in, and it's nice for performance to remove __getattribute__. __getattr__'s overhead isn't nearly as bad, but Descriptors are somewhat designed for this task :)

If I can get the attribute_name change in #16 implemented, I should have enough context to pr a Descriptor change (and then setting validators on Fields will be straightforward).

stevearc commented 10 years ago

Actually, there's already support for validators! I should probably call it out more in the docs, but right now you can pass a function to the Field() constructor. The function should accept a value and, if the value is incorrect, throw an error. The validators are only called when saving to the database. For example:

class String(object):
    def __init__(self, max_length):
        self.max_length = max_length

    def __call__(self, val):
        if len(val) > self.max_length:
            raise ValueError("String %r exceeds maximum length!" % val)

And then to use it you could do:

class MyModel(flywheel.Model):
    username = Field(check=String(18))
mortaliorchard commented 10 years ago

Thanks @stevearc / @numberoverzero for looking into this and taking the time to reply. Good to know the validators are already supported.

Issue resolved :)