'How to disable "HTML" tab in DRF Browsable API but keep "Raw" tab available

When using more complicated representation schemas (e.g. nested objects and lists), the "HTML" form part of the Browsable API in Django REST Framework becomes mostly unusable. How can I disable it while still keeping the rest of the Browsable API available, including the ability to POST/PUT/PATCH data using the other "Raw" tab?



Solution 1:[1]

Here's how I recently accomplished this.

Docs reference: https://www.django-rest-framework.org/topics/browsable-api/#advanced-customization

myproject/myapp/renderers.py

from rest_framework.renderers import BrowsableAPIRenderer


class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    """Overrides the standard DRF Browsable API renderer."""

    def get_context(self, *args, **kwargs):
        context = super(CustomBrowsableAPIRenderer, self).get_context(*args, **kwargs)
        # Remove "HTML" tabs
        context["post_form"] = None
        context["put_form"] = None
        return context

myproject/settings.py

REST_FRAMEWORK = {
    "DEFAULT_RENDERER_CLASSES": [
        "rest_framework.renderers.JSONRenderer",
        "myapp.renderers.CustomBrowsableAPIRenderer",  # Custom renderer
}

Solution 2:[2]

Haven't seen this documented, but in the source code:

    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """

https://github.com/encode/django-rest-framework/blob/3.9.x/rest_framework/renderers.py#L457-L463

It doesn't work quite as advertised, though. Returning None here will prevent "HTML" tab from being rendered, but it will also remove "DELETE" and "OPTIONS" buttons from the top of the page. To get only the effect of removing the "HTML" tab, overwriting render_form_for_serializer seems to do the trick:

class OnlyRawBrowsableAPIRenderer(BrowsableAPIRenderer):
    def render_form_for_serializer(self, serializer):
        return ""

Use it on specific View:

class MyModelViewSet(ModelViewSet):
    renderer_classes = [OnlyRawBrowsableAPIRenderer, JSONRenderer]
    ...

or using DEFAULT_RENDERER_CLASSES setting.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2