Title: pyramid/cornice validators and colander schema
Tags: validation;pyramid;colander;cornice
Question: I have a cornice API with a view that has validators and a colander schema. I can't get access to colander validated data (```request.validated```) in my validator.

I pass my data through colander. My colander schema looks something like this:

```from colander import (
    MappingSchema,
    SchemaNode,
    String
)

class UserSchemaRecord(MappingSchema):
    username = SchemaNode(String())
    password = SchemaNode(String())

class UserSchema(MappingSchema):
    user = UserSchemaRecord()
```

It adds a sanitized version of the request data into ```request.validated['user']``` that I can then access in my view like this.

```@view(renderer='json', validators=(valid_token, valid_new_username), schema=UserSchema)
def collection_post(self):
    """Adds a new user"""
    user_data = self.request.validated['user']
    user = UserModel(**user_data)
    DBSession.add(user)
    DBSession.flush()
    return {'user': user}
```

However, I also need to check that the request provides a unique username and return an error if the username is already taken. I'd like to do this with a validator (```valid_new_username```) but when I try to access ```request.validated['user']``` in my validator the data aren't there.

```def valid_new_username(request):
    user = request.validated['user'] # this line fails with a KeyError
    username = user['username']
    if UserModel.get_by_username(username):
        request.errors.add('body', 'username', "User '%s' already exists!" % username)
        request.errors.status = 409 # conflict
```

It looks like the validator is called before the data have been extracted. I don't really want to access the request json_body data directly before passing them through colander. Is there a way I can change the ordering of the schema/validator? 

The alternative is to do the checking directly in my view callable. Is that a good option? Are validators not supposed to work with colander validated data?


Here is the accepted answer: Not sure if it's your problem, but if the data is not valid in the first place (Colander found errors), then it will not be available as request.validated['key'] in the validators.

You can use a decorator like this if you want to apply the validator only if the data has passed Colander validation.

```def when_valid(validator):
    """Decorator for validation functions.
    Only try validation if no errors already.

    """
    def inner(request):
        if len(request.errors) &gt; 0:
            return
        validator(request)
    return inner

@when_valid
def valid_new_username(request):
    pass # your validation here
```

Comment for this answer: The code seems to point in that direction. https://github.com/mozilla-services/cornice/blob/f94dd6cc41c26dc648c97a526ed6071fb56e5c5b/cornice/service.py#L547-L560
Comment for this answer: Yes, it is. Thanks, I will use this a lot.
Comment for this answer: So schema validation always happens first?


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2015:00:09/13/15', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<validation><pyramid><colander><cornice>', 'Title': 'pyramid/cornice validators and colander schema', 'ViewCount': 708, 'id': 32553808, 'user_AboutMe': '<p>Academic primarily working in python to process, analyse and visualise energy consumption data.\nAlso have experience in Ruby, Ruby/Rails, Python/Pyramid, .NET, IDL</p>\n\n<p><a href="http://ggstuart.com" rel="nofollow">http://ggstuart.com</a></p>\n\n<p><a href="http://smartspaces.dmu.ac.uk" rel="nofollow">http://smartspaces.dmu.ac.uk</a></p>\n', 'user_AccountId': 1088547.0, 'user_DisplayName': 'Graeme Stuart', 'user_Reputation': 5387.0, 'user_Views': 314.0, 'user_id': 1083707.0}}