0

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?

4

1 回答 1

1

不确定这是否是您的问题,但如果数据一开始就无效(滤锅发现错误),那么它在验证器中将无法作为 request.validated['key'] 使用。

如果您只想在数据已通过滤锅验证时应用验证器,则可以使用这样的装饰器。

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

    """
    def inner(request):
        if len(request.errors) > 0:
            return
        validator(request)
    return inner

@when_valid
def valid_new_username(request):
    pass # your validation here
于 2015-09-14T12:57:28.177 回答