Flask-Inputs

WTForms is awesome for validating POST data. What about other request data?

The Flask-Inputs extension adds support for WTForms to validate request data from args to headers to json.

Installing Flask-Inputs

Install with pip:

pip install flask-inputs

Or download the latest version from Github:

git clone https://github.com/nathancahill/flask-inputs.git
cd flask-inputs
python setup.py install

Example Usage

Let’s say we have an API for customer data. Our route looks like this:

@api.route('/customer/<int:id>')
def customer(id):
    pass

Input validators are organized in a class, by type (args, headers, etc). We give each input field a list of validators. Let’s start by validating the URL rule:

from flask_inputs import Inputs
from wtforms.validators import DataRequired

class CustomerInputs(Inputs):
    rule = {
        'id': [DataRequired()]
    }

Like WTForms, built-in validators and custom validators are supported:

def customer_exists(form, field):
    if not Customer.query.get(field.data):
        raise ValidationError('Customer does not exist.')

class CustomerInputs(Inputs):
    rule = {
        'id': [DataRequired(), customer_exists]
    }

To validate the inputs, instantiate the Inputs class with the request object:

@api.route('/customer/<int:id>')
def customer(id):
    inputs = CustomerInputs(request)

    if not inputs.validate():
        return jsonify(success=False, errors=inputs.errors)

Adding more validators is easy now, like adding validation for API keys passed in the Authorization header:

class CustomerInputs(Inputs):
    rule = {
        'id': [DataRequired(), customer_exists]
    }
    headers = {
        'Authorization': [DataRequired(), valid_api_key]
    }

Advanced Usage

Inputs can be validated at any point in the request lifecylce. It can be helpful to put validation in a @before_request function, either in with an app or blueprint object:

from flask import Blueprint

api = Blueprint('api', __name__)

@api.before_request
def before():
    inputs = ApiInputs(request)

    if not inputs.validate():
        return jsonify(success=False, errors=inputs.errors)

Input objects also work with mixins, like WTForms. Common validators can be shared like this:

class ApiKeyValidation():
    headers = {
        'Authorization': [DataRequired(), valid_api_key]
    }

class CustomerInputs(Inputs, ApiKeyValidation):
    pass

class ProductInputs(Inputs, ApiKeyValidation):
    pass

This makes changing requirements in future simple. For example, if API keys are switched from the Authorization header to a key arg, it’s only needs to be changed in one place.

JSON Validation

Flask-Inputs supports JSON schema validation with jsonschema. JSON data posted in a request can be validated like this:

from flask_inputs.validators import JsonSchema

schema = {
    'type': 'object',
    'properties': {
        'name': {'type': 'string'}
    }
}

class JsonInputs(Inputs):
    json = [JsonSchema(schema=schema)]

API

class flask_inputs.Inputs(request)

Base class for input validation. Subclass to add validators.

Parameters:request – flask.Request object to validate.
errors = None

List of errors from all validators.

valid_attrs = ['args', 'form', 'values', 'cookies', 'headers', 'json', 'rule']

flask.Request attributes available for validation

validate()

Validate incoming request data. Returns True if all data is valid. Adds each of the validator’s error messages to Inputs.errors if not valid.

Returns:Boolean
class flask_inputs.validators.JsonSchema(schema, message=None)

Helper class for JSON validation using jsonschema.

Parameters:
  • schema – JSON schema to validate against.
  • message – Error message to return. Defaults to jsonschema’s errors.
Raises:

wtforms.validators.ValidationError