Browsable API
One of the defining features of DRF is its Browsable API. When an API endpoint is accessed from a web browser (as indicated by the Accept: text/html header), DRF renders the response using a beautifully formatted, interactive HTML interface.
NOTE
API may stand for Application Programming Interface, but humans have to be able to read the APIs, too. The Browsable API allows developers, clients and partners to easily explore, interact with and test the API directly in their browser without needing external tools like Postman or curl.
Why Use the Browsable API?
Before looking at how to configure it, it's important to understand why it's so powerful:
- Interactive Forms: For endpoints that support
POST,PUT, orPATCHmethods, the Browsable API automatically generates HTML forms based on the view's serializer. You can submit data directly from the browser. - Clickable URLs: If you include fully-qualified URLs in your resource output (using DRF's
reversehelper), they will be automatically "urlized" and made clickable for easy browsing. - Authentication Integration: The interface respects your configured authentication classes. If you are logged in, your session automatically applies to the Browsable API.
- Documentation: The docstring of your view class or function is automatically extracted and displayed as the description for the endpoint in the UI.
How It Works
The Browsable API is provided by the BrowsableAPIRenderer.
IMPORTANT
Default Behavior: This renderer is included by default in DRF's global DEFAULT_RENDERER_CLASSES setting. You do not need to configure anything to enable it.
When DRF detects that the request wants an HTML response, the BrowsableAPIRenderer takes the API data (which would normally be output as JSON) and renders it using a Django template to create the web interface.
You can explicitly request different formats in your browser by appending ?format=json or ?format=api to the URL.
WARNING
Form Rendering Overhead: To render HTML forms, the Browsable API asks the view for a serializer once per form (e.g., overriding the request method to POST, PUT, etc.). This means code branching on request.method (like get_serializer_class() or permission checks) will be executed multiple times during a single GET request to the Browsable API. This is expected behavior.
Authentication Routes
To quickly add authentication (login/logout functionality) directly to the Browsable API, you should add routes named "login" and "logout" under the "rest_framework" namespace. DRF provides default routes for this exact purpose, effectively eliminating boilerplate.
# urls.py
from django.urls import include, path
urlpatterns = [
# ... your other routes
path("api-auth/", include("rest_framework.urls", namespace="rest_framework"))
]Customizing the Theme
The Browsable API is built with Bootstrap, making it easy to customize the look-and-feel. You can change the color scheme or logo by overriding the default CSS or extending the base templates.
To customize the default style, create a file named rest_framework/api.html in your project's template directory that extends rest_framework/base.html:
<!-- templates/rest_framework/api.html -->
{% extends "rest_framework/base.html" %}
{% block branding %}
<a class="navbar-brand" href="/">My Custom API</a>
{% endblock %}
{% block bootstrap_theme %}
<!-- Completely replace the default Bootstrap theme -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@3.4.1/flatly/bootstrap.min.css" type="text/css">
{% endblock %}
{% block bootstrap_navbar_variant %}{% endblock %}TIP
Suitable pre-made replacement themes are available at Bootswatch. The empty bootstrap_navbar_variant block ensures the original Bootstrap navbar style is used instead of the default navbar-inverse.
Disabling the Browsable API
In a production environment, you might want to disable the Browsable API to reduce overhead or prevent users from accessing the interactive forms.
You can do this by removing BrowsableAPIRenderer from your global DEFAULT_RENDERER_CLASSES setting, or per-view.
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer', <- Removed
]
}from rest_framework.renderers import JSONRenderer
from rest_framework.views import APIView
class ProductionView(APIView):
# Only allow JSON, disabling the Browsable API for this view
renderer_classes = [JSONRenderer]
# ...