Standardize all Django REST Framework API responses into a consistent, predictable format
Project description
Django Response Formatter
Standardize all Django REST Framework API responses into a consistent, predictable format.
Every response — success or error — follows this structure:
{
"status": "success" | "error",
"message": "Human-readable message",
"data": { ... } | [ ... ] | null,
"errors": { ... } | null,
"metadata": { ... } | null
}
Installation
pip install dj-response-formatter
Quick Start
1. Add to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_response_formatter",
]
2. Configure DRF settings:
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES": [
"django_response_formatter.renderers.FormattedJSONRenderer",
],
"EXCEPTION_HANDLER": "django_response_formatter.exceptions.format_exception_handler",
}
3. (Optional) Add middleware for non-DRF exception handling:
MIDDLEWARE = [
# ... other middleware ...
"django_response_formatter.middleware.ResponseFormatterMiddleware",
]
That's it. All your API responses are now formatted consistently.
Response Examples
Success (2xx)
# View
class UserView(APIView):
def get(self, request, pk):
user = get_object_or_404(User, pk=pk)
return Response(UserSerializer(user).data)
{
"status": "success",
"message": "Request was successful.",
"data": {
"id": 1,
"username": "john",
"email": "john@example.com"
},
"errors": null,
"metadata": null
}
Validation Error (400)
{
"status": "error",
"message": "Bad request.",
"data": null,
"errors": {
"email": ["This field is required."],
"username": ["A user with that username already exists."]
},
"metadata": {
"status_code": 400
}
}
Not Found (404)
{
"status": "error",
"message": "Not found.",
"data": null,
"errors": null,
"metadata": {
"status_code": 404
}
}
Paginated Response
DRF pagination metadata is automatically extracted:
{
"status": "success",
"message": "Request was successful.",
"data": [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"}
],
"errors": null,
"metadata": {
"pagination": {
"count": 100,
"next": "http://api.example.com/items/?page=2",
"previous": null
}
}
}
Helper Functions
Use the helper functions for explicit control over response messages:
from django_response_formatter.helpers import success_response, error_response, raw_response
class UserView(APIView):
def get(self, request, pk):
user = get_object_or_404(User, pk=pk)
return success_response(
data=UserSerializer(user).data,
message="User retrieved successfully.",
)
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return success_response(
data=serializer.data,
message="User created.",
status_code=201,
)
return error_response(
errors=serializer.errors,
message="Validation failed.",
status_code=400,
)
success_response(data=None, message=None, status_code=200, headers=None)
Returns a DRF Response that the renderer formats as a success envelope.
error_response(errors=None, message=None, status_code=400, headers=None)
Returns a DRF Response that the renderer formats as an error envelope.
raw_response(data=None, status_code=200, headers=None)
Returns a DRF Response that skips formatting entirely. Use for health checks, webhooks, or any endpoint that must return raw JSON.
Configuration
Customize behavior via the RESPONSE_FORMATTER dict in your Django settings:
RESPONSE_FORMATTER = {
# Field names in the envelope
"STATUS_FIELD": "status",
"MESSAGE_FIELD": "message",
"DATA_FIELD": "data",
"ERRORS_FIELD": "errors",
"METADATA_FIELD": "metadata",
# Status values
"SUCCESS_STATUS": "success",
"ERROR_STATUS": "error",
# Default messages
"DEFAULT_SUCCESS_MESSAGE": "Request was successful.",
"DEFAULT_ERROR_MESSAGE": "An error occurred.",
# Include fields even when their value is null
"INCLUDE_NULL_FIELDS": True,
# Extract pagination info into metadata automatically
"EXTRACT_PAGINATION": True,
# Pagination field names to detect
"PAGINATION_FIELDS": ["count", "next", "previous", "page_size", "total_pages"],
}
Example: Minimal Responses
RESPONSE_FORMATTER = {
"INCLUDE_NULL_FIELDS": False,
}
A success response now omits null fields:
{
"status": "success",
"message": "Request was successful.",
"data": {"id": 1}
}
Example: Custom Field Names
RESPONSE_FORMATTER = {
"STATUS_FIELD": "ok",
"DATA_FIELD": "result",
"SUCCESS_STATUS": True,
"ERROR_STATUS": False,
}
{
"ok": true,
"message": "Request was successful.",
"result": {"id": 1},
"errors": null,
"metadata": null
}
Components
| Component | Purpose |
|---|---|
FormattedJSONRenderer |
Wraps all DRF responses in the standardized envelope |
format_exception_handler |
Normalizes DRF exception data for consistent error formatting |
ResponseFormatterMiddleware |
Catches unhandled exceptions outside DRF views (optional) |
success_response / error_response / raw_response |
View helpers for explicit control |
Requirements
- Python >= 3.9
- Django >= 4.2
- Django REST Framework >= 3.14
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dj_response_formatter-0.1.0.tar.gz.
File metadata
- Download URL: dj_response_formatter-0.1.0.tar.gz
- Upload date:
- Size: 15.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99cab0ae6329c71ac43170043b46e0fdae1ee612b5508be90a7924451df0ab71
|
|
| MD5 |
47806914e21410bee9399d0a344cbef1
|
|
| BLAKE2b-256 |
d94a32ef351417c3de14e53e2fa685ac48704f5dd97052eefd72abe452af1119
|
Provenance
The following attestation bundles were made for dj_response_formatter-0.1.0.tar.gz:
Publisher:
publish.yml on suomynonAnonymous/django-response-formatter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dj_response_formatter-0.1.0.tar.gz -
Subject digest:
99cab0ae6329c71ac43170043b46e0fdae1ee612b5508be90a7924451df0ab71 - Sigstore transparency entry: 1393624535
- Sigstore integration time:
-
Permalink:
suomynonAnonymous/django-response-formatter@7ae32af083ccca6624e5649d1ebe572240f71cc0 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/suomynonAnonymous
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7ae32af083ccca6624e5649d1ebe572240f71cc0 -
Trigger Event:
release
-
Statement type:
File details
Details for the file dj_response_formatter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dj_response_formatter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb3d160703626643517ead22505c27a5d8ef9843d69ba78025c57114c1cf5162
|
|
| MD5 |
5539aa9486d94939c47e2cedda69878e
|
|
| BLAKE2b-256 |
1abce7ac125d4cd184e26bfc18f2d88beb942264a48138beda61a2cd8ad3a3f7
|
Provenance
The following attestation bundles were made for dj_response_formatter-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on suomynonAnonymous/django-response-formatter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dj_response_formatter-0.1.0-py3-none-any.whl -
Subject digest:
bb3d160703626643517ead22505c27a5d8ef9843d69ba78025c57114c1cf5162 - Sigstore transparency entry: 1393624545
- Sigstore integration time:
-
Permalink:
suomynonAnonymous/django-response-formatter@7ae32af083ccca6624e5649d1ebe572240f71cc0 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/suomynonAnonymous
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7ae32af083ccca6624e5649d1ebe572240f71cc0 -
Trigger Event:
release
-
Statement type: