Extending Cerberus

Custom Validators

Cerberus supports custom validation in two styles:

As a general rule, when you are customizing validators in your application, Class-based style is more suitable for common validators, which are also more human-readable (since the rule name is defined by yourself), while Function-based style is more suitable for special and one-off ones.

Class-based Custom Validators

Suppose that in our use case some values can only be expressed as odd integers, therefore we decide to add support for a new isodd rule to our validation schema:

schema = {'oddity': {'isodd': True, 'type': 'integer'}}

This is how we would go to implement that:

from cerberus import Validator

class MyValidator(Validator):
    def _validate_isodd(self, isodd, field, value):
        if isodd and not bool(value & 1):
            self._error(field, "Must be an odd number")

By subclassing Cerberus Validator class and adding the custom _validate_<rulename> function, we just enhanced Cerberus to suit our needs. The custom rule isodd is now available in our schema and, what really matters, we can use it to validate all odd values:

>>> v = MyValidator(schema)
>>> v.validate({'oddity': 10})
False
>>> v.errors
{'oddity': 'Must be an odd number'}
>>> v.validate({'oddity': 9})
True

In a schema schema you can use space characters instead of underscores, e.g. {'oddity': {'is odd': 42'}} is an alias for {'oddity': {'is_odd': 42'}}.

New in version 0.7.1: Custom validators also have access to a special self.document variable that allows validation of a field to happen in context of the rest of the document.

To make use of additional contextual information in a sub-class of Validator, use a pattern like this:

class MyValidator(Validator):
    def __init__(self, *args, **kwargs):
        if 'additional_context' in kwargs:
            self.additional_context = kwargs['additional_context']
        super(MyValidator, self).__init__(*args, **kwargs)

    def _validate_type_foo(self, field, value):
        make_use_of(self.additional_context)

New in version 0.9.

Custom Data Types

Cerberus supports and validates several standard data types (see type). When building Class-based Custom Validators you can add and validate your own data types. For example Eve (a tool for quickly building and deploying RESTful Web Services) supports a custom objectid type, which is used to validate that field values conform to the BSON/MongoDB ObjectId format.

You extend the supported set of data types by adding a _validate_type_<typename> method to your own Validator subclass. This snippet, directly from Eve source, shows how the objectid has been implemented:

def _validate_type_objectid(self, field, value):
    """ Enables validation for `objectid` schema attribute.

    :param field: field name.
    :param value: field value.
    """
    if not re.match('[a-f0-9]{24}', value):
        self._error(field, ERROR_BAD_TYPE.format('ObjectId'))

New in version 0.0.2.

Function-based Custom Validation

With a special rule validator, you can customize validators by defining your own functions with the following prototype:

def validate_<fieldname>(field, value, error):
    pass

As a contrast, if the odd value is a special case, you may want to make the above rule isodd into Function-based style, which is a more lightweight alternative:

def validate_oddity(field, value, error):
    if not bool(value & 1):
        error(field, "Must be an odd number")

Then, you can validate an odd value like this:

>>> schema = {'oddity': {'validator': validate_oddity}}
>>> v = Validator(schema)
>>> v.validate({'oddity': 10})
False
>>> v.errors
{'oddity': 'Must be an odd number'}

>>> v.validate({'oddity': 9})
True

New in version 0.8.

Limitations

You must not call your custom rule validator and it may be a bad idea to overwrite particular contributed rules.

Relevant Validator-properties

Validator.__get_child_validator

If you need another instance of your Validator-subclass, the __get_child_validator-method returns another instance that is initiated with the same arguments as self was. You can specify overriding keyword- arguments.

New in version 0.9.

Validator.root_document

A child-validator - as used when validating a schema - can access the first generation validator’s document that is being processed via its root_document-property. It’s untested what happens when you change that. It may make boom.

New in version 0.10.