Skip to content

Requests & Responses

Django REST Framework introduces its own Request and Response objects that extend Django's standard HttpRequest and HttpResponse respectively. These custom objects provide a more flexible and powerful interface for building web APIs.

Requests

DRF's Request object provides a few crucial properties that make building APIs easier:

.data

request.data is the core of DRF's request processing. It returns the parsed content of the request body (typically a dictionary or list).

  • Works for POST, PUT and PATCH requests.
  • Handles parsing multiple content types (JSON, form data, file uploads) transparently based on the Parsers configured for the view.
  • Replaces standard Django's request.POST and request.FILES.
python
# Instead of this:
data = request.POST

# Do this:
data = request.data

.query_params

A more accurately named synonym for request.GET.

Since a GET object typically implies a GET HTTP method, request.query_params makes it clear that you are accessing query string parameters, which can be present on any HTTP request (e.g., POST /api/users/?active=true).

.user & .auth

  • request.user: Returns an instance of django.contrib.auth.models.User (or your custom user model) if the request is authenticated. Otherwise, it returns django.contrib.auth.models.AnonymousUser.
  • request.auth: Returns any additional authentication context. For example, when using token authentication, this will be the exact token object used to authenticate the request. If the request is unauthenticated, or if no additional context is present, the default value of request.auth is None.

Other Request Properties

PropertyDescription
.parsersA list of parser instances that the view has configured to process the request body.
.accepted_rendererThe renderer instance selected by content negotiation to format the response.
.accepted_media_typeA string representing the accepted media type chosen by the content negotiation phase.
.authenticatorsA list of authenticator instances configured for the view.
.methodThe uppercase string representation of the HTTP method (e.g., 'GET', 'POST'). It transparently handles HTTP method spoofing if enabled.
.content_typeA string representing the media type of the HTTP body.
.streamReturns a stream representing the raw content of the request body.

NOTE

Since DRF's Request extends Django's HttpRequest, all standard attributes and methods are also available. For example, the request.META and request.session dictionaries are available as normal.

Responses

DRF's Response object extends Django's SimpleTemplateResponse. Instead of passing a pre-rendered string (like HTML or raw JSON) to the response, you pass unrendered, basic Python data structures.

DRF then uses Content Negotiation to determine the appropriate Renderer to format the data for the client.

Instantiating a Response

The standard signature is Response(data, status=None, template_name=None, headers=None, content_type=None).

  • data: The unrendered data (a dict, list, or primitive) to be serialized.
  • status: The HTTP status code. Defaults to 200 OK.
  • template_name: A template name to use if HTMLRenderer is selected.
  • headers: A dictionary of HTTP headers to include in the response.
  • content_type: The content type of the response. Typically, this will be set automatically by the renderer as determined by content negotiation, but there may be some cases where you need to specify the content type explicitly.

TIP

Always use DRF's explicit status code variables (e.g., status.HTTP_400_BAD_REQUEST instead of 400) to keep your views readable and self-documenting.

Example Usage

python
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView

class ExampleView(APIView):
    def get(self, request):
        data = {"message": "Hello, world!"}
        return Response(data, status=status.HTTP_200_OK)
        
    def post(self, request):
        # We can read parsed request.data and return unrendered data
        received = request.data
        if not received:
            return Response(
                {"error": "No data provided"}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        return Response(received, status=status.HTTP_201_CREATED)

Why Unrendered Data?

By returning native Python structures instead of a raw JSON string, your view remains decoupled from the specific output format. This allows DRF to serve the same view as JSON, XML, or even a browsable HTML interface, depending on the client's Accept header.

Response Properties

PropertyDescription
.dataThe unrendered, serialized data provided to the Response when it was instantiated.
.status_codeThe numeric HTTP status code of the response.
.contentThe rendered content of the response. This is typically only available after the .render() method has been called.
.template_nameThe template name supplied when instantiating the response, if any.
.accepted_rendererThe renderer instance used to render the response.
.accepted_media_typeThe media type string chosen by the content negotiation phase.
.renderer_contextA dictionary of context information passed to the renderer's .render() method.

NOTE

Since DRF's Response extends Django's SimpleTemplateResponse, all standard attributes and methods are also available.