The Django REST framework and Django side by side
I guess all Django developers share a common story. They built a lot of stuff and tried the mini-framework approach à la Flask, but in the end, they always returned to Django simply because it is opinionated, and it offers all the tools for building full-stack web applications with Python. The Django REST Framework is a Django package that follows the same pragmatic approach. In this chapter, we compare the Django REST Framework to Django, and we explore the asynchronous Django landscape.
What Is the Django REST Framework?
The Django REST Framework (DRF for short) is a Django package for building Web APIs.
Class-based REST views
This chapter isn’t intended as a guide to the DRF for beginners, but it is worth spending some words to go over the main building blocks of this package. In the next sections, we explore these components, since they will be the Lego blocks for the first part of our decoupled Django project.
Class-Based Views in Django and the DRF
When building web applications, some common patterns for handling data insertion and data listing repeat over and over.
Displaying the form, either empty or with initial data
Validating the user input and showing eventual errors
Saving the data to the database
CreateView and UpdateView for POST requests
ListView and DetailView for GET requests
DeleteView for DELETE requests
CreateAPIView for POST requests
ListAPIView and RetrieveAPIView for GET requests
DestroyAPIView for DELETE requests
UpdateAPIView for PUT and PATCH requests
In addition, you can peruse a combination of CBVs for retrieve/delete operations like RetrieveDestroyAPIView, or for retrieve/update/destroy like RetrieveUpdateDestroyAPIView. You will use a lot of these CBVs in your decoupled Django projects to speed up development of the most common tasks, although the DRF offers a more powerful layer on top of CBVs, called viewsets.
For a complete list of class-based views in Django, see ccbv.co.uk. For the Django REST Framework, see cdrf.co.
CRUD Viewsets in DRF
In Chapter 1, we reviewed the concept of resources as one of the main building blocks of REST.
A ModelViewSet in DRF
Relationship Between Viewset Methods, HTTP Methods, and CRUD Operations
list() / retrieve()
Partial update resource
Viewset and Urlpatterns in Django REST
As you can see, with a minimal amount of code you have the complete collection of CRUD operations, with the corresponding URLs.
Models, Forms, and Serializers
The ability to create pages and forms with little or no code at all is what makes Django shine.
A Django Model
A DRF Serializer
A DRF Serializer
A JSON Response with Relationships
In Chapter 6, we use serializers to decouple our Django project. Having outlined the building blocks of the DRF, let’s now explore the wonderful world of asynchronous Django.
From WSGI to ASGI
WSGI is the lingua franca of web servers to Python communication, that is, a protocol that enables the back and forth between web servers such as Gunicorn, and the underlying Python application.
As anticipated in Chapter 2, Django needs a web server to run efficiently in production. Usually, a reverse proxy such as NGINX acts as the main entry point for the end user. A Python WSGI server listens for requests behind NGINX and acts as a bridge between the HTTP request and the Django application. Everything happens synchronously in WSGI, and there was no way to rewrite the protocol without introducing breaking changes. That led the community (for this tremendous work we must thank Andrew Godwin) to write a new protocol, called ASGI, for running asynchronous Python applications under ASGI-capable web servers. To run Django asynchronously, and we are going to see what that means in the next section, we need an asynchronous-capable server. You can choose Daphne, Hypercorn, or Uvicorn. In our example, we will use Uvicorn.
Getting Started with Asynchronous Django
Asynchronous code is all about non-blocking execution. This is the magic behind platforms like Node.js, which predated the realm of high throughput services for years.
A Synchronous View Doing Network Calls
This should immediately raise a red flag. It can run fast, really fast, or take forever to complete, leaving the browser hanging. Due to the single-threaded nature of the Python interpreter, our code runs in sequential steps. In our view, we can’t return the response to the user until the API call completes. In fact my link, https://api.valentinog.com/demo/sleep/, is configured to sleep for 10 seconds before returning the result. In other words, our view is blocking. Here httpx, the Python HTTP client I use to make requests, is configured with a safe timeout and will raise an exception after a few seconds, but not every library has this sort of security in place.
An Asynchronous View Doing Network Calls, This Time Safely
Using an Asynchronous Context Manager
An asynchronous context manager is one that implements __aenter__ and __aexit__ instead of __enter__ and __exit__.
Efficiently execute multiple HTTP requests in parallel in a view
Schedule long-running tasks
Interact safely with external systems
There are still things missing before Django and the DRF become 100% asynchronous—the ORM and the Django REST views are not asynchronous—but we will use asynchronous Django capabilities here and there in our decoupled project to practice.
Competing Asynchronous Frameworks and the DRF
At the time of writing, the Django REST Framework has no support for asynchronous views.
In light of this, wouldn’t it be better to use something like FastAPI or Starlette for building asynchronous web services? Starlette is an ASGI framework built by Tom Christie, the DRF creator. FastAPI instead builds on top of Starlette and offers a stellar developer tooling for building asynchronous Web APIs. Both are excellent choices for greenfield projects, and luckily you don’t have to choose, because FastAPI can run within Django itself, thanks to experimental projects like django-ninja, while we wait for asynchronous DRF.
What are the DRF class-based views, viewsets, and serializers
How to create and asynchronous Django view
How to run Django under Uvicorn