Django for APIs is a project-based guide to building modern APIs with Django & Django REST Framework. It is suitable for beginners who have never built an API before as well as professional programmers looking for a fast-paced introduction to Django fundamentals and best practices.
These are essential notes and code snippets from the book that help in extending any existing Django website into web API with minimal effort, covering everything from scratch to hosting and API documentation. We'll be discussing the basics of the Django Rest Framework in Part II. Let's begin!
Read Part I here
Django Rest Framework
Django creates websites containing webpages, while Django REST Framework creates web APIs which are a collection of URL endpoints containing available HTTP verbs that return JSON.
wsgi.py
stands for web server gateway interface and helps Django serve the eventual web pages
There are three main steps to convert your database models into a RESTful API are:
- a
urls.py
file for the URL routes - a
serializers.py
file to transform the data into JSON - a
views.py
file to apply logic to each API endpoint
Serializers
A serializer translates data into a format that is easy to consume over the internet, typically JSON and is displayed at an API endpoint.
NOTES:
- Always add a
__str__
method to provide a human-readable name for each future model instance.- Migration files are a fantastic way to debug applications and you should strive to create a migration file for each small change. If we had updated the models in two different apps and then run
python manage.py makemigrations
the resulting single migration file would contain data on both apps. That just makes debugging harder. Try to keep your migrations as small as possible.
CORS - Cross-Origin Resource Sharing
Whenever a client interacts with an API hosted on a different domain (mysite.com vs yoursite.com) or port (localhost:3000 vs localhost:8000) there are potential security issues.
Specifically, CORS requires the server to include specific HTTP headers that allow the client to determine if and when cross-domain requests should be allowed.
The easiest way to handle this–-and the one recommended by Django REST Framework–-is to use middleware that will automatically include the appropriate HTTP headers based on our settings.
We use django-cors-headers
:
- add
corsheaders
to theINSTALLED_APPS
- add
CorsMiddleware
aboveCommonMiddleWare
inMIDDLEWARE
- create a
CORS_ORIGIN_WHITELIST
NOTE:
It’s very important that
corsheaders.middleware.CorsMiddleware
appears in the proper location. That is abovedjango.middleware.common.CommonMiddleware
in theMIDDLEWARE
setting since middlewares are loaded top-to-bottom.
Permissions
Django REST Framework ships with several out-of-the-box permissions settings that we can use to secure our API. These can be applied at a project-level, a view-level, or at any individual model level.
Add login to the browsable API
This is such a common occurrence that Django REST Framework has a one-line setting to add login and log out directly to the browsable API itself.
Within the project-level
urls.py
file, add a new URL route that includesrest_framework.urls
. Somewhat confusingly, the actual route specified can be anything
we want; what matters is thatrest_framework.urls
is included somewhere.
Code:
# blog_project/urls.py
from django.urls import include, path
urlpatterns = [
...
path('api-auth/', include('rest_framework.urls')), # new
]
Project-Level Permissions
Django REST Framework ships with a number of built-in project-level permissions settings we can use, including:
- AllowAny - any user, authenticated or not, has full access
- IsAuthenticated - only authenticated, registered users have access
- IsAdminUser - only admins/superusers have access
- IsAuthenticatedOrReadOnly - unauthorized users can view any page, but only authenticated users have write, edit, or delete privileges
Implementing any of these four settings requires updating the DEFAULT_PERMISSION_CLASSES
setting:
# blog_project/settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', # new
]
}
Note:
- If a request contains HTTP verbs included in
SAFE_METHODS
– a tuple containingGET
,OPTIONS
, andHEAD
–then it is a read-only request, and permission is granted.- The generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views–for a collection of instances–you’ll need to filter by overriding the initial queryset.
Conclusion:
Setting proper permissions is a very important part of any API. As a general strategy, it is a good idea to set a strict project-level permissions policy such that only authenticated users can view the API. Then make view-level or custom permissions more accessible as needed on specific API endpoints.
Read Part III here
Find more about it on the GitHub repo:
https://github.com/PragatiVerma18/Django-For-APIs
If you enjoyed reading these notes, then do let me know your views in the comments. In case you want to connect with me, follow the links below:
LinkedIn | GitHub | Twitter | StackOverflow
Top comments (4)
Amazing article!
Thank you so much, Aditya 😊
Nice work, Pragati.
Thanks, Anubhav 😊