Request objects
REST framework introduces aRequest object that extends the regular HttpRequest, and provides more flexible request parsing. The core functionality of the Request object is the request.data attribute, which is similar to request.POST, but more useful for working with Web APIs.
Key Features of Request Objects
Flexible Parsing
The
request.data attribute handles JSON, form data, and file uploads automatically based on the content type.Method Agnostic
Works with POST, PUT, and PATCH methods, unlike
request.POST which only works with POST.Response objects
REST framework also introduces aResponse object, which is a type of TemplateResponse that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.
Response object automatically handles:
- Content negotiation
- Rendering to the appropriate format (JSON, HTML, etc.)
- Setting the correct content-type header
Status codes
Using numeric HTTP status codes in your views doesn’t always make for obvious reading, and it’s easy to not notice if you get an error code wrong. REST framework provides more explicit identifiers for each status code, such asHTTP_400_BAD_REQUEST in the status module. It’s a good idea to use these throughout rather than using numeric identifiers.
Wrapping API views
REST framework provides two wrappers you can use to write API views.
These wrappers provide a few bits of functionality such as:
- Making sure you receive
Requestinstances in your view - Adding context to
Responseobjects so that content negotiation can be performed - Returning
405 Method Not Allowedresponses when appropriate - Handling any
ParseErrorexceptions that occur when accessingrequest.datawith malformed input
Pulling it all together
Okay, let’s go ahead and start using these new components to refactor our views slightly.snippets/views.py
views.py module:
snippets/views.py
Notice that we’re no longer explicitly tying our requests or responses to a given content type.
request.data can handle incoming json requests, but it can also handle other formats. Similarly we’re returning response objects with data, but allowing REST framework to render the response into the correct content type for us.Adding optional format suffixes to our URLs
To take advantage of the fact that our responses are no longer hardwired to a single content type let’s add support for format suffixes to our API endpoints. Using format suffixes gives us URLs that explicitly refer to a given format, and means our API will be able to handle URLs such ashttp://example.com/api/items/4.json.
Start by adding a format keyword argument to both of the views, like so:
snippets/urls.py file slightly, to append a set of format_suffix_patterns in addition to the existing URLs:
snippets/urls.py
How’s it looking?
Go ahead and test the API from the command line, as we did in tutorial part 1. Everything is working pretty similarly, although we’ve got some nicer error handling if we send invalid requests. We can get a list of all of the snippets, as before:Content Negotiation
We can control the format of the response that we get back, either by using theAccept header:
Content-Type header:
Browsability
Now go and open the API in a web browser, by visiting http://127.0.0.1:8000/snippets/. Because the API chooses the content type of the response based on the client request, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a web browser. This allows for the API to return a fully web-browsable HTML representation. Having a web-browsable API is a huge usability win, and makes developing and using your API much easier. It also dramatically lowers the barrier-to-entry for other developers wanting to inspect and work with your API.See the browsable API topic for more information about the browsable API feature and how to customize it.
