drf-friendly-errors-mod 0.13.10
Extension for displaying serializer validation errors in Django Rest Framework
License: MIT

DRF Friendly Errors
===================

**Extension for Django REST framework error display**

Overview
--------

This package extends default error JSON body providing configurable error codes
and more consumable response structure.

It turns default JSON body of HTTP 400 response, which look like this:

.. code:: python

    {
        "name": ["This field is required."],
        "password": ["This field may not be blank."]
    }

into

.. code:: python

    {
        "name" : [
            {
                "code" : 2002,
                "detail" : "This field is required."
            }
        ],
        "password" : [
            {
                "code" : 2031,
                "detail" : "This field may not be blank."
            }
        ]
    }

Library handles all `Django REST framework`_ built-in serializer validation.

Requirements
------------
-  Python (2.7, 3.5, 3.6, 3.7)
-  Django (<2.0, >=1.8)
-  Django REST framework (<3.9, >=3.5)

Installation
------------

By running installation script

.. code:: bash

    $ python setup.py install

Or using pip

.. code:: bash

    $ pip install drf-friendly-errors-mod

Usage
-----

Simply add a ErrorMessagesMixin to your serializer or model serializer class

.. code:: python

    from rest_framework_friendly_errors.mixins import ErrorMessagesMixin

    class MySerializer(ErrorMessagesMixin, ModelSerializer):

If you want to change default library settings and provide your own set of error codes just add following in your
settings.py

.. code:: python

    FRIENDLY_ERRORS = {
        "FIELD_ERRORS": {
            'CharField': {'required': 10, 'null':11, 'blank': 12, 'max_length': 13, 'min_length': 14}
        },
        "VALIDATOR_ERRORS": {
            'UniqueValidator': 50
        },
        "EXCEPTION_DICT": {
            'PermissionDenied': 100
        }
    }

Custom serializer validation
----------------------------

If you need custom field validation or validation for whole serializer register your validation in serializer class

.. code:: python

    class PostSerializer(ErrorMessagesMixin,
                         serializers.ModelSerializer):
        class Meta:
            model = Post

        def validate_title(self, value):
            if value[0] != value[0].upper():
                raise ValidationError('First letter must be an uppercase')
            return value

        def validate(self, attrs):
            category = attrs.get('category)
            title = attrs.get('title')
            if category and category not in title:
                raise ValidationError('Title has to include category')
            return attrs

        FIELD_VALIDATION_ERRORS = {'validate_title': 5000} # register your own validation method and assign it to error code
        NON_FIELD_ERRORS = {'Title has to include category': 8000} # register non field error messages and assign it to error code

If you want to raise field error in validate method use register_error method provided by a mixin

.. code:: python

    class PostSerializer(ErrorMessagesMixin,
                         serializers.ModelSerializer):
        class Meta:
            model = Post

        def validate(self, attrs):
            category = attrs.get('category')
            title = attrs.get('title')
            if category and category not in title:
                self.register_error(error_message='Title has to include category',
                                    error_code=8000,
                                    field_name='title')
            return attrs

Error codes not related to serializer validation
------------------------------------------------

To turn other type of errors responses into friendly errors responses with error codes
add this exception handler to your REST_FRAMEWORK settings

.. code:: python

    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER':
        'rest_framework_friendly_errors.handlers.drf_exception_handler'
    }

Default error codes
-------------------

Following conventions were used:

1xxx - Are reserved for non field errors

2xxx - Are reserved for field errors

3xxx - Are reserved for validator errors

4xxx - Are reserved for other errors not related to serializer validation

Default field error codes
-------------------------

Field is required

- 2001: BooleanField, NullBooleanField
- 2002: CharField, EmailField, PasswordField, RegexField, SlugField, URLField, UUIDField, FilePathField, IPAddressField
- 2003: IntegerField, FloatField, DecimalField
- 2004: ChoiceField, MultipleChoiceField
- 2005: FileField, ImageField
- 2006: ListField, DictField, JSONField
- 2007: StringRequiredField, PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityField, ManyRelatedField
- 2008: ReadOnlyField, HiddenField, ModelField, SerializerMethodField

Field data is invalid (invalid regex, string instead of number, date, etc.)

- 2011: BooleanField, NullBooleanField
- 2012: CharField, EmailField, PasswordField, RegexField, SlugField, URLField, UUIDField, IPAddressField
- 2013: IntegerField, FloatField, DecimalField
- 2014: FileField, ImageField
- 2015: DateTimeField, DateField, TimeField, DurationField

Field data cannot be null

- 2021: BooleanField, NullBooleanField
- 2022: CharField, EmailField, PasswordField, RegexField, SlugField, URLField, UUIDField, FilePathField, IPAddressField
- 2023: IntegerField, FloatField, DecimalField
- 2024: ChoiceField, MultipleChoiceField
- 2025: FileField, ImageField
- 2026: ListField, DictField, JSONField
- 2027: StringRequiredField, PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityField, ManyRelatedField
- 2028: ReadOnlyField, HiddenField, ModelField, SerializerMethodField

Field data cannot be blank

- 2031: CharField, EmailField, PasswordField, RegexField, SlugField, URLField, UUIDField, IPAddressField

Field data is too long string

- 2041: CharField, EmailField, PasswordField, RegexField, SlugField, URLField, UUIDField, IPAddressField
- 2042: IntegerField, FloatField, DecimalField
- 2043: FileField, ImageField

Field data is too short string

- 2051: CharField, EmailField, PasswordField, RegexField, SlugField, URLField, UUIDField, IPAddressField

Field data is too big number

- 2061: IntegerField, FloatField, DecimalField

Field data is too small number

- 2071: IntegerField, FloatField, DecimalField

Field data do not match any value from available choices

- 2081: ChoiceField, MultipleChoiceField
- 2082: FilePathField
- 2083: ManyRelatedField

Field is empty

- 2091: FileField, ImageField
- 2092: MultipleChoiceField
- 2093: ManyRelatedField

File has no name

- 2101: FileField, ImageField

File is an invalid image

- 2111: ImageField

Field is not a list

- 2121: MultipleChoiceField
- 2122: ListField
- 2123: ManyRelatedField

Field is not a dict

- 2131: DictField

Field is not a json

- 2141: JSONField

Field does not exist (invalid hyperlink, primary key, etc.)

- 2151: PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityField

Incorrect type for relation key

- 2161: PrimaryKeyRelatedField, HyperlinkedRelatedField, SlugRelatedField, HyperlinkedIdentityField

Couldn't match url or name to a view

- 2171: HyperlinkedRelatedField, HyperlinkedIdentityField

Expected a DateTime, got Date

- 2181: DateTimeField

Excpected a Date, got DateTime

- 2191: DateField

Too many digits for defined Decimal

- 2201: DecimalField

Too many whole digits for defined Decimal

- 2211: DecimalField

Too many decimal digits for defined Decimal

- 2221: DecimalField

Default built-in validators error codes
---------------------------------------

- UniqueValidator: 3001
- UniqueTogetherValidator: 3003
- UniqueForDateValidator: 3004
- UniqueForMonthValidator: 3004
- UniqueForYearValidator: 3005
- RegexValidator: 3006
- EmailValidator: 3007
- URLValidator: 3008
- MaxValueValidator: 3009
- MinValueValidator: 3010
- MaxLengthValidator: 3011
- MinLengthValidator: 3012
- DecimalValidator: 3013
- validate_email: 3014
- validate_slug: 3015
- validate_unicode_slug: 3016
- validate_ipv4_address: 3017
- validate_ipv46_address: 3018
- validate_comma_separated_integer_list: 3019
- int_list_validator: 3020

Other error codes not related to serializer validation
------------------------------------------------------
- Server Error: 4000
- Parser Error (exception was raised by Parser class): 4001,
- Authentication Failed (invalid credentials were provided): 4002,
- Not Authenticated (no credentials were provided): 4003,
- Not Found: 4004,
- HTTP 404: 4004,
- Permission Denied: 4005,
- Method Not Allowed (invalid HTTP method): 4006,
- Not Acceptable (Could not satisfy the request Accept header): 4007,
- Unsupported Media-Type: 4008,
- Throttled (Too many requests): 4009

Tests
-----

Pull requests won't be accepted without passing tests. You can run the test suite with:

.. code:: python

    python runtests.py

.. _Django Rest framework: http://django-rest-framework.org/

Contributors
------------
- Geoffrey Lehée <socketubs>