The RESTful API architecture
DRF is an extension of Django for developing and deploying RESTful APIs.
- Introducing RESTful APIs
- Building RESTful APIs with DRF
- Error handling
Introduction
RESTful APIs cover the following basic parts:
intro
-
Resources:
The information a client can request where the API gathers the information per entity as a resource such as a customer or product. In the example of
Figure 5.1
, the trip is a resource. And for our sample microservices application, the address is a resource. -
Endpoints:
The URLs where the API exposes itself and clients send requests.
And RESTful APIs process these parts to handle requests:
-
HTTP methods: The methods a client uses to send a request to an API:
methods
- GET request: Retrieve data about a resource
- POST request: Create a resource
- PATCH request: Update a resource partially
- PUT request: Overwrite a resource entirely
- DELETE request: Remove a resource
-
Parameters: The options clients send to an endpoint to retrieve specific resource information or to authenticate:
parameters
- Header: Such as an API security key to authorize a request
- Path: As part of the called URL to address a specific resource
- Query string: As part of the called URL to select a subset of resources
-
Request body: The JSON or XML objects a client sends to an API as resource data
Let’s bring these parts together in some curl
examples. The first example requests a list of all hostels in the Tripadvisor system:
Building RESTful APIs with DRF
DRF is an extension of Django for developing and deploying RESTful APIs.
Abstract
DRF provides us with these functionalities:
- The actual API that clients can access through one or more endpoints
- Serializers that collaborate with Django ORM to transform data from data source to JSON and the other way around
- A set of pre-defined views to quickly and easily create API endpoints for CRUD operation
DRF
If we transpose this to Django and zoom in on the Django file structure, we’ll see that DRF is primarily about these standard Django files:
- models.py: Containing the data model for our API
- views.py: Containing the API viewset and specifications for CRUD operations
- urls.py: Containing the endpoints for our API views
There is also this specific DRF file:
- serializers.py: Containing the serialization specification for the model
These files work closely together as the serializer
; the view
uses the model
(the serializer), and the URL
file uses the view.
With this in mind, let’s start building a RESTful API for our subscription application
The RESTful API will have this directory structure:
subscription_apis/
│
├── address_api/
│ ├── models.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
│
├── subscription_apis/
│ ├── urls.py
│ └── settings.py
│
└── manage.py
And to build the RESTful API, we’ll take this route:
- Setting up DRF
- Creating a model and a serializer
- Creating a view and a URL file for the endpoints
Creating a view and the URL endpoints
DRF was first released in 2011, and over time, the view mechanism evolved from function-based
to class-based
views
Function-based views are, as their name implies, based on a Python function, which defines the view’s behavior. A function becomes a function-based view by decorating it like this:
@api_view(['GET', 'POST'])
def address_list(request):
if request.method == 'GET':
...
elif request.method == 'POST':
...
The @api-view
decorator promotes the address_list
function to a function-based
view, which clients can access through the GET and POST methods. Consequently, the if
... elif
section handles GET
and POST
requests.
Likewise, class-based views are based on DRF-specific Python classes:
class AddressViewSet(viewsets.ModelViewSet):
queryset = Address.objects.all()
serializer_class = AddressSerializer
The generic ModelViewSet
class integrates all HTTP methods, including PUT
and DELETE
, and covers most RESTful API requirements. All we have to do is specify a queryset
object and a serializer_class
object for the viewset, and DRF takes care of the rest.
Despite the evolution from function-based
to class-based
views, both view types still exist today, and their characteristics and differences come down to this:
Important note
In general, apply class-based views if you can and function-based views if you must because of some specific functionalities offered only by function-based views.