FastAPI vs. Django: Which to Use and When?
FastAPI and Django are two of the most popular Python web frameworks out there. They both provide excellent features for developers to create robust web applications.
But when it comes to deciding between FastAPI vs. Django, there is no one-size-fits-all answer. Each framework is unique and may have its pros and cons based on factors like project requirements, architecture choices, and development experience.
In this article, we’ve put together a comprehensive guide that examines FastAPI vs Django with examples to help you decide the best one for your project.
Django
Django is the older and more established web framework with a larger and more established community. It comes with an ORM, a templating engine, an administrative interface, forms, and many other features.
With Django, you can build a web application end-to-end using Python.
FastAPI
FastAPI is a new, Python-based micro-framework for implementing APIs. It's lightweight and focuses on high performance.
Compared to Django, FastAPI has a focus on API development. It's minimalistic and requires the developer to choose third-party modules based on their preference. For example, you need to choose which ORM you are going to use with FastAPI.
Besides, if you are building a web application, you may need to select the frontend framework as well.
Django vs FastAPI
Let's compare and contrast the major differences between these frameworks.
Security
Django has multiple built-in security features to prevent issues like cross-site scripting, cross-site request forgery, SQL injections, and clickjacking. Since it's a complete web framework, it provides support for configuring HTTPS, SSL certificates, host header validations, etc.
FastAPI is minimalistic even when it comes to its core security features. It provides a separate security module for API security supporting OAuth2, OpenID Connect, and OpenAPI. However, if you are building a web application, you may need additional measures to establish security with FastAPI.
Therefore, when it comes to web applications, Django provides a complete end-to-end solution. With FastAPI you need to take additional measures to enforce security.
Performance
Django has multiple built-in caching options to improve application performance. You can choose database caching, file system caching, local memory caching, or dummy caching as required.
For example, if you are implementing database caching, you need to update the settings.py
file with the below code and run python manage.py
createcachetable
command.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'table_name',
}
}
On the other hand, FastAPI is designed with performance in mind at its core. It has a simple and lightweight architecture based on Starlette and Uvicorn. Further, FastAPI encourages rapid development and improves development speed by about 200% - 300% while reducing 40% of human-induced errors. In terms of caching with FastAPI, there are third-party options to choose from. For example, you can use fastapi-cache library to cache your API responses.
Overall, both Django and FastAPI provide good performance. But, FastAPI is much faster than Django, and benchmark studies also suggest that FastAPI has the best performance of all Python frameworks.
Dependency Injection
Dependency injection is an important design pattern used in modern software development. It helps to implement inversion of control where you can write code that depends on interfaces where the implementation of that interface can be passed from outside. This greatly helps in loosely coupling the application logic with other modules in the system.
Django supports dependency injection through a third-party module named Django Injector. It allows you to inject dependencies into Django views, Django RESTFramework (DRF) views, Django template context processors, and DRF view sets.
The below code shows a simple example of Django dependency injection.
from django_injector import inject
from my_app.services import ArticleService
@inject
def my_view(request, article__service: ArticleService):
return article__service.get_articles(request)
In the above example, the my_view function is getting a request
and an injected service named Article Service
.
On the other hand, FastAPI provides a straightforward and user-friendly dependency injection solution and makes it easier to inject database connections, services, shared codes, and authentication features within the application.
The below code shows a simple example of FastAPI dependency injection.
from fastapi import Depends, FastAPI
app = FastAPI()
async def properties(offset: int = 0, limit: int = 50):
return {"offset": offset, "limit": limit}
@app.get("/articles/")
async def get_articles(params: dict = Depends(properties)):
return params
@app.get("/writers/")
async def get_writers(params: dict = Depends(properties)):
return params
The above example uses the Depends
function provided by FastAPI to implement dependency injection. Here, offset
and limit
values are injected into each endpoint as dependencies and endpoints do not have knowledge of offset
and limit
variable values. Hence, changing or updating those properties without affecting the endpoints is easy.
Overall, both Django and FastAPI support dependency injection. But, you have to use a third-party module with Django to implement dependency injection.
Templating Language
Django has its own text-based template language designed to generate dynamic HTML. The syntax is quite similar to Smarty and Jinja2.
You can generate Django templates in any text-based file format like HTML, XML, CSV, etc. Templates mainly consist of variables and tags. Variables are dynamically replaced at runtime, and tags will control the logic.
The below code shows a simple example of a Django template.
{% extends "base_generic.html" %}
{% block title %}{{ article.title }}{% endblock %}
{% block content %}
# {{ article.title }}
<h4>
< a href="{{ article.writer_profile_url}}">{{ article.writer_name|upper }}</a>
</h4>
{{ article.content}}
{% endblock %}
Compared to Django, FastAPI has more flexibility with template languages. It supports almost all template engines. The below example shows how to create a template with FastAPI and Jinja2.
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
# Creating a template object
templates = Jinja2Templates(directory="templates")
# Using the template object to render and retrn a response
@app.get("/articles/{id}", response_class=HTMLResponse)
async def get_article_id(request: Request, id: str):
return templates.TemplateResponse("article.html", {"request": request, "id": id})
Then, you can create a template named article.html
and display the details.
<html>
<head>
<title>Article List</title>
<link href="{{ url_for('static', path='/styles.css') }}" rel="stylesheet">
</head>
<body>
# Article ID: [[WIDGET_PLACEHOLDER_id]]
</body>
</html>
In conclusion, FastAPI has a wide range of template language support compared to Django.
API Documentation Generation Support
Both Django and FastAPI provide automatic API documentation generation support.
In Django, you must use third-party modules like drf_yasg and install Django Rest Framework to enable automatic API documentation. For example, you can include descriptions for APIs like the below:
class ListArticleAPIView(ListAPIView):
"""Lists all articles from the database"""
queryset = Article.objects.all()
serializer_class = ArticleSerializer
class CreateArticleAPIView(CreateAPIView):
"""Creates a new article"""
queryset = Article.objects.all()
serializer_class = ArticleSerializer