Skip to main content

Django Rest Framework Simple API Errors

PyPI test workflow codecov pyversions

What is this?

A library for Django Rest Framework returning consistent, predictable and easy-to-parse API error messages.

This library was built with RFC7807 guidelines in mind, but with a small twist: it defines a "problem detail" as a list instead of a string, but it still serves as a way to include errors in a human-readable and easy-to-parse format for any API consumer. Error messages are formatted using RFC7807 keywords and DRF exception data.

Unlike standard DRF, where the error response format varies depending on the error source, this library always returns errors in a consistent and predictable structure.

What's different?

Compared to other similar and popular libraries, this library:

  • Is based on RFC7807 guidelines
  • Aims to provide not only a standardized format for error details, but also human-readable error messages (perfect for both internal and public APIs)
  • Transforms both django.core.exceptions.ValidationError and rest_framework.errors.ValidationError to API errors, so you don't have to handle error raised by services/domain logic, clean(), etc.

Table of Contents

Installation

Install using the command line:

pip install drf-simple-api-errors

Usage

Exception Handler

Add EXCEPTION_HANDLER in your REST_FRAMEWORK settings of your Django project settings file:

REST_FRAMEWORK = {
    # Your other settings...
    "EXCEPTION_HANDLER": "drf_simple_api_errors.exception_handler",
}

Error structure overview

API error messages will include the following keys:

  • "title" (str): A brief summary that describes the problem type.
  • "detail" (list[str] | None): A list of specific explanations related to the problem, if any.
  • "invalid_params" (list[dict] | None): A list of dict containing details about parameters that were invalid or malformed in the request, if any. Each dict within this list provides:
    • "name" (str): The name of the parameter that was found to be invalid.
    • "reasons" (list[str]): A list of strings describing the specific reasons why the parameter was considered invalid or malformed.
{
  "title": "Error message.",
  "detail": ["error"],
  "invalid_params": [
    {
      "name": "field_name",
      "reason": ["error"]
    }
  ]
}

Example JSON Error Responses

Field validation errors

{
  "title": "Error message.",
  "detail": null,
  "invalid_params": [
    {
      "name": "field_name",
      "reason": ["error"]
    }
  ]
}

Non-fields validation errors

{
  "title": "Error message.",
  "detail": ["error"],
  "invalid_params": null
}

Other bad requests with no detail

{
  "title": "Error message.",
  "detail": null,
  "invalid_params": null
}

Settings

Default settings:

DRF_SIMPLE_API_ERRORS = {
    "CAMELIZE": False,
    "EXTRA_HANDLERS": [],
    "FIELDS_SEPARATOR": ".",
}
  • CAMELIZE

Camel case support for Django Rest Framework exceptions JSON error responses.

If CAMELIZE is set to True:

{
  "title": "Error message.",
  "detail": null,
  "invalidParams": [
    {
      "name": "fieldName",
      "reason": ["error"]
    }
  ]
}
  • EXTRA_HANDLERS

Support for exceptions that differ from the standard structure of the Django Rest Framework.

For example, if you need to customize how a specific exception is handled or want to format an existing exception differently, you can create your own handler.

To customize error handling for your project, simply create a new file (for example, extra_handlers.py) and define your own handler functions. This approach lets you tailor error responses to fit your specific needs.

Then add it to the EXTRA_HANDLERS list in this package settings:

DRF_SIMPLE_API_ERRORS = {
    "EXTRA_HANDLERS": [
        "path.to.my.extra_handlers.custom_handler",
        # ...
    ]
}

For reference, this library uses the same pattern for its own extra handlers here.

  • FIELDS_SEPARATOR

Support for nested dicts containing multiple fields to be flattened.

If FIELDS_SEPARATOR is set to .:

{
    "field1": {
        "field2": "value"
    }
}

Will result in:

{
    "field1.field2": "value"
}

Integration with drf-spectacular

This library provides a drf-spectacular postprocessing hook that adds standardized error response schemas to your OpenAPI documentation.

Install with drf-spectacular support:

pip install drf-simple-api-errors[openapi]

Then add the postprocessing hook to your SPECTACULAR_SETTINGS:

SPECTACULAR_SETTINGS = {
    # Your other settings...
    "POSTPROCESSING_HOOKS": [
        # Only if you use djangorestframework-camel-case
        "drf_spectacular.contrib.djangorestframework_camel_case.camelize_serializer_fields",
        # Always include the hooks below
        "drf_spectacular.hooks.postprocess_schema_enums",
        "drf_simple_api_errors.integrations.spectacular.postprocess_schema_inject_errors",
    ],
}

The hook:

  • Defines reusable APIError and InvalidParam schema components
  • Adds error responses (400, 401, 403, 404, 500) to all API operations
  • Respects the CAMELIZE setting for property names. When your API uses djangorestframework-camel-case, also include camelize_serializer_fields in POSTPROCESSING_HOOKS (as shown above) so request/response bodies and the injected error schemas stay consistently camel-cased.
  • Does not overwrite error responses you have explicitly defined via @extend_schema

Place postprocess_schema_inject_errors last in POSTPROCESSING_HOOKS so any prior hooks have already shaped the operations before responses are injected.

By default, the hook injects responses for status codes 400, 401, 403, 404, and 500 on every operation. If some of those codes only apply to specific endpoints (e.g. 400 and 404), restrict the dict to codes that apply universally and declare the rest per-operation via @extend_schema:

DRF_SIMPLE_API_ERRORS = {
    # Your other settings...

    # Only inject universally applicable error responses (e.g. 401, 403, 500)
    "SPECTACULAR_ERROR_STATUS_CODES": {
        "401": "Unauthorized",
        "403": "Forbidden",
        "500": "Server error",
    },
}

N.B. If SPECTACULAR_ERROR_STATUS_CODES is set to an empty dict, only the APIError and InvalidParam schema components are injected — no error responses are attached to operations.

Support

Please open an issue.

Contributing

Please use the Github Flow. In a nutshell, create a branch, commit your code, and open a pull request.

Testing

All the necessary commands are included in the Makefile.

We are using tox and poetry to run tests in every supported Python version.

Run test during development with the commands below:

make install  # only if necessary
make test

Finally, run tox to ensure the changes work for every supported python version:

pip install tox  # only if necessary
tox -v

Metadata

Release files for drf-simple-api-errors 2.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for drf-simple-api-errors 2.2.0
File Size Uploaded
drf_simple_api_errors-2.2.0.tar.gz 14.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for drf-simple-api-errors 2.2.0
File Interpreter ABI Platform
drf_simple_api_errors-2.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.5 kB

Release files / drf_simple_api_errors-2.2.0.tar.gz

Download URL drf_simple_api_errors-2.2.0.tar.gz
Size 14.5 kB
Tags Source
SHA-256 checksum
How to use checksums
78b56f1aa3c7af905e0f2aabf425e4e2d492bc924d3f62f23c4f720ef77143e1
BLAKE2b-256 checksum
How to use checksums
cfb0ce788c06f22c01182c55ad0e6ee7e21ef46d237e1c6d7285e96e8a0666fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.10.20 Linux/6.17.0-1015-azure

Release files / drf_simple_api_errors-2.2.0-py3-none-any.whl

Download URL drf_simple_api_errors-2.2.0-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1e071a29dc546021e6b37a68b79ac307c147def9307c0e0f1d88d5ed6e241be0
BLAKE2b-256 checksum
How to use checksums
a28903cd130a7c6dcb80cc8f0e383e692096feb0eac914c7b7a974a9f2e06a71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.10.20 Linux/6.17.0-1015-azure

Release history Release notifications | RSS feed

This release

2.2.0 This release

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page