Fields, Translation, and Validation

This topic describes how to translate and validate parameters from a request.

Translation is the process of converting the incoming parameter (typically a string) into the desired type. For example, there may be a request such as the following: http://mydomain.com/resource?count=20. The count parameter would be a string, however we would want to use it as an integer. Therefore, we would cast/translate it to an integer. This can encapsulate more than just casting (e.g. turning a JSON string into a dict.

Validation takes the translated parameter and ensures that it fulfills a certain set of expectations. In the previous example, we may wish to validate that the count query argument is always greater than 0.

Simple Example

This example demonstrates how to perform simple translation and validation on an count parameter

from ripozo import translate, fields, apimethod, ResourceBase, RequestContainer

class MyResource(ResourceBase):

    @apimethod(methods=['GET'])
    @translate(fields=[fields.IntegerField('count', minimum=1)], validate=True)
    def hello(cls, request):
        count = request.get('count')
        return cls(properties=dict(count=count))

The translate decorator translates the inputs using a series of fields. If we pass validate=True to the translate decorator, it will perform validation as well. The list of fields passed to the fields parameter must all be instances of BaseField . BaseField classes perform the actual translation and validation for a given field.

>>> req = RequestContainer(query_args=dict(count='3'))
>>> res = MyResource.hello(req)
>>> res.properties['count'] == 3
True
>>> req = RequestContainer(query_args=dict(count='0'))
>>> res = MyResource.hello(req)
Traceback (most recent call last):
    ...
ValidationException: The field "count" is required and cannot be None
>>> req = RequestContainer(query_args=dict(count='not an integer'))
>>> res = MyResource.hello(req)
Traceback (most recent call last):
    ...
TranslationException: Not a valid integer type: not an integer

We can see that the string is appropriately cast in the first attempt and passes validation. The second example raises a ValidationException because it was id<1 which we specified as the minimum. Finally, the last example raises a TranslationException because the id parameter was not a valid integer.

Specifying the location

By default, the translate decorator will look in the url parameters, query arguments and body arguments when finding the parameter to check. For example, the following still works

>>> req = RequestContainer(body_args=dict(count='3'))
>>> res = MyResource.hello(req)
>>> res.properties['count'] == 3
True

However, sometimes we may require that a parameter is only allowed in a specific location. With ripozo, this is very simple.

from ripozo.resources.constants.input_categories import QUERY_ARGS

# we'll declare the fields here for cleanliness
# Note the arg_type parameter which specifies to
# only look in the query args for this field
hello_fields = [fields.IntegerField('count', required=True, minimum=1, arg_type=QUERY_ARGS)]

class MyResource(ResourceBase):

    @apimethod(methods=['GET'])
    @translate(fields=hello_fields, validate=True)
    def hello(cls, request):
        count = request.get('count')
        return cls(properties=dict(count=count))

The previous example, will no longer work since the field is only allowed to be from the query arguments.

>>> req = RequestContainer(body_args=dict(count='3'))
>>> res = MyResource.hello(req)
Traceback (most recent call last):
    ...
ValidationException: The field "count" is required and cannot be None
>>> req = RequestContainer(query_args=dict(count='3'))
>>> res = MyResource.hello(req)
>>> res.properties['count'] == 3
True

With this method, we could even translate and validate two fields with the same name as long as they are in different locations.

Creating special fields

While there are plenty of fields available in Field types, sometimes, you need something more specific. In this example we’ll show you how to create an email validation field.

To create a new field, you simply need to inherit from ripozo.resources.fields.base.BaseField and override the necessary methods, in particular the _translate and _validate methods.

from ripozo import fields
from ripozo.exceptions import ValidationException

class EmailField(fields.BaseField):
    def _validate(self, obj, **kwargs):
        # perform the standard validation such as whether it is required.
        obj = super(EmailField, self)._validate(obj, **kwargs)
        if obj is None:  # In case it wasn't a required field.
            return obj
        if '@' not in obj:
            raise ValidationException('"{0}" is not a valid email address'.format(obj))
        return obj

We could then test this by running the following

>>> field = EmailField('email_address', required=True)
>>> field.translate('some@email.com', validate=True)
'some@email.com'
>>> field.translate('not an email', validate=True)
Traceback (most recent call last):
    ...
ValidationException: "not an email" is not a valid email address

We can then use this new field like the IntegerField we used previously.

API Documentation

Translation and Validation Decorators

class ripozo.decorators.translate(fields=None, skip_required=False, validate=False, manager_field_validators=False)[source]

Decorator for validating the inputs to an apimethod and describing what is allowed for that apimethod to an adapter if necessary.

Example usage:

from ripozo import translate, fields, apimethod, ResourceBase, RequestContainer

class MyResource(ResourceBase):

    @apimethod(methods=['GET'])
    @translate(fields=[fields.IntegerField('id', required=True)], validate=True)
    def hello(cls, request):
        id_ = request.query_args['id']
        print(id_)
>>> req = RequestContainer(query_args=dict(id=3))
>>> res = MyResource.hello(req)
3
>>> req = RequestContainer()
>>> res = MyResource.hello(req)
Traceback (most recent call last):
    ...
ValidationException: The field "id" is required and cannot be None
>>> req = RequestContainer(query_args=dict(id='not an integer'))
>>> res = MyResource.hello(req)
Traceback (most recent call last):
    ...
TranslationException: Not a valid integer type: not an integer
__call__(func)[source]

Wraps the function with translation and validation. This allows the inputs to be cast and validated as necessary. Additionally, it provides the adapter with information about what is necessary to successfully make a request to the wrapped apimethod.

Parameters:func (method) – The function to decorate
Returns:The wrapped function
Return type:function
__init__(fields=None, skip_required=False, validate=False, manager_field_validators=False)[source]

Initializes the decorator with the necessary fields. the fields should be instances of FieldBase and should give descriptions of the parameter and how to input them (i.e. query or body parameter). To perform validation of the fields as well, set validate=True

Parameters:
  • fields (list) – A list of FieldBase instances (or subclasses of FieldBase).
  • skip_required (bool) – If this flag is set to True, then required fields will be considered optional. This is useful for an update when using the manager_field_validators as this allows the user to skip over required fields like the primary keys which should not be required in the updated arguments.
  • validate (bool) – Indicates whether the validations should be run. If it is False, it will only translate the fields and no validation will occur.
  • manager_field_validators (bool) – (Deprecated: will be removed in v2) A flag indicating that the fields from the Resource’s manager should be used.
__weakref__

list of weak references to the object (if defined)

fields(manager)[source]

Gets the fields from the manager if necessary.

class ripozo.decorators.manager_translate(fields=None, skip_required=False, validate=False, fields_attr=u'fields')[source]

A special case translation and validation for using managers. Performs the same actions as ripozo.decorators.translate but it inspects the manager to get the resources necessary.

Additionally, you can tell it what fields to get from the manager via the fields_attr. This will look up the fields on the manager to return.

__call__(func)[source]

Wraps the function with translation and validation. This allows the inputs to be cast and validated as necessary. Additionally, it provides the adapter with information about what is necessary to successfully make a request to the wrapped apimethod.

Parameters:f (method) –
Returns:The wrapped function
Return type:function
__init__(fields=None, skip_required=False, validate=False, fields_attr=u'fields')[source]

A special case translation that inspects the manager to get the relevant fields. This is purely for ease of use and may not be maintained

Parameters:
  • fields (list[ripozo.resources.fields.base.BaseField]) – A list of fields to translate
  • skip_required (bool) – If true, it will not require any of the fields. Only relevant when validate is True
  • validate (bool) – A flag that indicates whether validation should occur.
  • fields_attr (str|unicode) – The name of the attribute to access on the manager to get the fields that are necessary. e.g. ‘create_fields’, ‘list_fields’ or whatever you want. The attribute should be a list of strings
__weakref__

list of weak references to the object (if defined)

fields(manager)[source]

Gets the fields from the manager

Parameters:manager (ripozo.manager_base.BaseManager) –

Field types

Contains common field types that may be used.

class ripozo.resources.fields.common.BooleanField(name, required=False, error_message=None, arg_type=None)[source]

A field used for translating and validating a boolean input It can take either a boolean or a string. If it’s a string it checks if it matches ‘false’ or ‘true’ (case insensitive).

field_type

alias of bool

class ripozo.resources.fields.common.DateTimeField(name, valid_formats=None, minimum=None, maximum=None, **kwargs)[source]

A field for validating and translating a datetime input. By default it accepts the following formats:

%Y-%m-%dT%H:%M:%S.%fZ

If you need other formats simply pass a list of valid formats into the valid_formats parameter on initialization

__init__(name, valid_formats=None, minimum=None, maximum=None, **kwargs)[source]
Parameters:
  • name (unicode) – The name of the field
  • valid_formats (list) – A list of datetime formats that are valid for translation. By default it accepts %Y-%m-%dT%H:%M:%S.%fZ
field_type

alias of datetime

class ripozo.resources.fields.common.DictField(name, field_list=None, minimum=None, maximum=None, **kwargs)[source]

A field for a dictionary of objects. Each named sub-field can be mapped to individual fields (Or even nested DictField’s).

__init__(name, field_list=None, minimum=None, maximum=None, **kwargs)[source]

Calls super and sets the field_dict on the object.

Parameters:
  • name (unicode) – The name of this field.
  • field_list (list) – A list of fields the names of the fields are what is used as the key in the dictionary.
  • kwargs (dict) – The standard arguments for BaseField.__init__
field_type

alias of dict

translate(obj, **kwargs)[source]

Translates and Validates the dictionary field and each of it’s contained fields. It will iterate over this field_dict and translate and validate each of the individual key, value pairs.

Parameters:obj (dict) – The object to translate and validate (if validate=True)
Returns:The translated (and possibly validated) object.
Return type:dict
class ripozo.resources.fields.common.FloatField(name, regex=None, minimum=None, maximum=None, **kwargs)[source]

A field used for translating and validating a float input. Pretty much the same as the IntegerField except that it will be cast as an IntegerField.

field_type

alias of float

class ripozo.resources.fields.common.IntegerField(name, regex=None, minimum=None, maximum=None, **kwargs)[source]

A field used for translating and validating an integer input. While translating it will attempt to cast the object provided as an integer.

field_type

alias of int

class ripozo.resources.fields.common.ListField(name, indv_field=None, minimum=None, maximum=None, **kwargs)[source]

A field for a list of objects. A field for the individual results can also be provided. This would be run against every individual item in the list that is provided.

__init__(name, indv_field=None, minimum=None, maximum=None, **kwargs)[source]
Parameters:
  • name (unicode) – The name of the field.
  • indv_field (BaseField) – The field to use when translating and validating individual items in the list.
field_type

alias of list

translate(obj, **kwargs)[source]

Translates the object into a list.

Parameters:obj (object) – The object to translate.
Returns:The translated/validated object.
Return type:list
class ripozo.resources.fields.common.StringField(name, regex=None, minimum=None, maximum=None, **kwargs)[source]

Used for casting and validating string fields.

__init__(name, regex=None, minimum=None, maximum=None, **kwargs)[source]

A field class for validating string inputs.

Parameters:
  • name (unicode) – The name of the field
  • regex (_sre.SRE_Pattern) – A compiled regular expression that must match at least once.
  • kwargs (dict) – The additional arguments to pass to the super call.
field_type

alias of unicode

Contains the base field that every other field should inherits from..

class ripozo.resources.fields.base.BaseField(name, required=False, maximum=None, minimum=None, arg_type=None, error_message=None)[source]

The BaseField class is simply an abstract base class that defines the necessary methods for casting and validating a field.

__weakref__

list of weak references to the object (if defined)

field_type

alias of object

translate(obj, skip_required=False, validate=False)[source]

A shortcut method to _translate and _validate the object that is being passed in. It returns this object or raises a ValueError.

Parameters:obj (object) –
Returns:The translated and validated object
Return type:object
Raises:ripozo.exceptions.ValidationsException
Raises:ripozo.exceptions.TranslationException
ripozo.resources.fields.base.translate_fields(request, fields=None, skip_required=False, validate=False)[source]
Performs the specified action on the field. The action can be a string of
either _translate, _validate, or translate.
Parameters:
  • request (RequestContainer) – The request that you are attempting to translate from.
  • fields (list) – The list of BaseField instances that are supposed to be validated. Only items in this list will be translated and validated
  • skip_required (bool) – A flag that indicates the required fields are not required. This is helpful for updates where fields are not usually required.
  • validate (bool) – A flag that indicates whether the field validations should be run. If not, it will just translate the fields.
Returns:

Returns the translated url_params, query_args and body_args

Return type:

tuple

Raises:

RestException

Raises:

ValidationException

Raises:

TranslationException