Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

Web Interface and Renderers

Here are resources for DRF renderers:

00:00 In the previous lesson, I introduced you to DRF ViewSets. In this lesson, I’m going to show you the built-in web interface and explain how renderers work.

00:11 Built into the DRF is a web interface. The same URLs I’ve been showing you in previous lessons, if you hit those with a web browser instead of something like curl, you’ll get a full HTML page including the payload and the ability to run actions on the objects.

00:27 How does DRF know what to respond with? Well, there’s two answers to that question. First, what renderers are installed, and second, what HTTP Accept headers are sent. For example, if you had a YAML and an HTML renderer installed and your program sent the following Accept header, accepting JSON, indented JSON, YAML, HTML, and everything else, then YAML would be used because it’s the first renderer that matches that Accept string. Up until now, when I’ve been using curl in the demonstration, curl by default accepts */*, so it hits the first renderer installed, which by default is the JSON renderer.

01:13 You can affect what renderers are used by changing a setting in settings.py. Declare the REST_FRAMEWORK dictionary with a 'DEFAULT_RENDERER_CLASSES' attribute, and that specifies what renderers to use. What’s showing here is actually the default. If you don’t specify anything in settings.py, this will be what you get.

01:33 This says to use the JSON renderer and then the web API renderer. As I mentioned, curl accepts everything, and because JSONRenderer is declared first, this will be what matches. In a production system, you may not want to use these default renderers. As an example, the web renderer will download all sorts of options for choice fields, so if you have a field with thousands of possible choices available to it, the browser will download this every single time. By making the web renderer available, you are potentially opening yourself up to a Denial-of-Service attack.

02:09 It’s very handy to have this renderer when you’re debugging, but it’s not a bad idea to turn it off once you go into production. The web renderer also makes your API far more discoverable.

02:20 A lot of information is presented. All of that information is still query-able through other renderers, but it makes it easier to find. Security through obscurity isn’t a valid approach, but why make it easy on people?

02:35 In addition to setting the renderer inside of settings.py at a global level, you can also set it specifically. For example, in a view class, you can use the @renderer_classes decorator to specify what renderers are valid with a view.

02:50 This one only supports the JSONRenderer. Notice that the parameter to the decorator is a list, so you can specify multiple renderers if you wish.

03:00 Alternatively, you can also set it inside of a ViewSet. ViewSets inherit from APIView class and all APIView classes support a attribute called .renderer_classes.

03:12 This is similar to using the decorator in the previous example, but it sets the renderer for all of the actions associated with this ViewSet.

03:22 The DRF comes with a bunch of different choices for renderers. You’ve seen the JSONRenderer already. The TemplateHTMLRenderer uses Django’s template engine to render whatever template you pass it. The StaticHTMLRenderer takes a string, which is supposed to contain HTML. You still use the DRF Response object, but in this case you pass it the string that you want rendered. The BrowsableAPIRenderer is the web renderer which I’ve been talking about and will show you shortly.

03:52 The AdminRenderer is similar to the BrowsableAPIRenderer, but the interface looks like the Django admin instead of the default.

04:01 The HTMLFormRenderer renders a HTML form object. Typically this isn’t used on its own, but used in conjunction with a template, which is then fetching a form.

04:13 The forms are then based on the body of the REST elements. The MultiPartRenderer is another one that isn’t used on its own. This is also for forms, but in this case, multipart forms, and typically is only used for testing.

04:28 In addition to all of those, there are a whole bunch of third-party packages as well, supporting YAML; XML; if you’re not happy with the format of the JSON, there’s multiple different types of JSON so you can make it look just about however you like; MessagePack; Excel; CSV files; a variety of Pandas-based plugins, which support CSV, Excel, and PNG; and LaTeX, of all things.

04:55 The DRF renderer system has been built so that you can customize it and create your own. If you want to look into this, you can look at the API guide in the renderers section.

05:06 And now let me demo the web interface. In a window offscreen, I’m running the Django dev server. I’m going to hit the same artifacts/ URL that I showed you with curl in the previous lesson. And here’s the web interface.

05:20 The API root view is whatever you defined inside of the DefaultRouter. At the moment, all I have defined is the "artifacts" section. Down here in the body of the response, you see the headers that came back as well as the payload.

05:34 This is just like the curl view before but has the added benefit of the link is now clickable. Clicking the link gives me the .retrieve() method, the list of artifacts—in this case, showing the two artifacts that are in the database. If I scroll down, there’s a form that complies with the ArtifactSerializer.

06:00 Clicking POST will call the .create() method in REST. The end result on the screen is the newly created object, with {"id": 3, "name": "Golden Idol", "shiny" : True}. In the breadcrumbs at the top, I can go back to the artifact list,

06:17 and now you’ll notice I’ve got three objects in the database. I can modify the URL at the top and specify a particular ID, doing a .retrieve().

06:31 And here you are back at the detail information for artifact 3. Notice this Allow header tells you just what HTTP methods are available for this particular object. Because the ArtifactViewSet was default, it supports all of the possible HTTP methods. Scrolling down once again, I can change the form, click on PUT, and this will cause an .update() to happen. Just like before, I’ve changed the artifact from shiny to not-so-shiny.

07:03 Along the top there’s a DELETE button so that I can call the .delete() method. It confirms, which I approve, and it tells me that the object has been deleted.

07:14 Notice that the URL is still for object number 3, but there’s no information here because there’s no content for object number 3. Clicking back on the Artifact List, I’m back to having just the two objects.

07:28 If you’re tired of the web interface and want to see exactly what comes back, you can change the format of the GET using this button on the right-hand side. By selecting json, the page now comes back as JSON.

07:41 This particular view is what Firefox does with JSON. Clicking on Raw Data shows you what actually came back.

07:50 As you can see, this is a really powerful and useful tool. I use it almost continually whenever I’m trying to debug my REST APIs.

07:59 That’s it for the web interface. Next up, I’ll show you how to control access using DRF permissions.

Become a Member to join the conversation.