Download Free Install Free

Flask vs. Django: Choose Your Python Web Framework

Table of Contents

Flask or Django?

According to the 2018 Python Developers Survey, Flask and Django are, by far, the most popular web frameworks for Python developers. You’ll hardly go wrong with either framework if you’re deciding which one to use for a new web application.

While it’s up to you to figure out which one works best for what you’re trying to accomplish, there’s a few major differences you should be aware of when making the decision. Regardless of which framework you end up using, both are very well documented and widely used, so they have ample active and supportive communities.

So, without further ado, let’s take a look at what each framework offers and highlight some of their differences and similarities.

TL;DR Flask vs Django Differences

Flask and Django are mature, extensible web frameworks that, at their core, offer similar functionality in handling requests and serving up documents, but differ in their scope of responsibility.

Most of the differences between the 2 frameworks stem from this different approach although some also stem from some different core design decisions.

Here is a short list of key differences that might impact your decision:

  • The Request Object – Flask uses thread-locals while Django passes the request around where it’s needed.
  • Forms – Django comes with them built-in and they integrate with the ORM and the admin site. Flask has no default support for forms, but you can use WTForms to fill the gap.
  • The Database – Django comes with the Django ORM and a migration system that wants to manage your database. Flask makes no assumptions about a database, but there are tools out there, like SQLAlchemy that provide similar functionality (perhaps more).
  • Authentication & Permissions – Django comes with an authentication app that gives a default implementation for user management and permissions. Flask provides secure cookies as a tool for your own implementation.
  • Admin Site – Django comes with a fully integrated admin interface for managing application data. Flask doesn’t come with anything like it, but Flask-Admin is a popular extension that can be used to create a similar admin tool.

What is Django?

Django’s website states that “Django makes it easier to build better Web apps more quickly and with less code,” and calls Django “the web framework for perfectionists with deadlines”. Indeed, Django is a mature framework that (by default) makes many decisions on its own so that the user has that cookie-cutter utility needed in a typical web application.

If you’re happy with most of those decisions and the defaults Django provides, you can have a relatively complex web application running in quite a short time.

Some companies that use Django:

  • Instagram
  • Pinterest
  • Udemy
  • Coursera
  • Zapier

What is Flask?

The Flask website describes Flask as “a microframework for Python based on Werkzeug, Jinja 2 and good intentions” and sports the slogan “web development, one drop at a time.” Once again, this gives you a good sense of the space Flask tries to fill in the overcrowded world of Python web frameworks.

Specifically, Flask aims to serve as a minimal framework that handles a few things well, but then leaves more of the decisions on how you want to build your web application up to you – either through custom implementations or any number of 3rd party extensions.

Companies that use Flask:

  • Netflix
  • Lyft
  • Reddit
  • Zillow
  • MailGun

How do these different approaches pan out?

To better understand the similarities and differences between Flask and Django, let’s take a look at what they offer through the scope of some high-level features you might find in typical web applications.

The development environment

Development Server

Both Django and Flask come packaged with development servers that make it easy and convenient to get started on building your web application quickly. They come with features that you’d expect from a mature web framework, such as the ability to handle requests, serve static files (for development), and detect when your code changes in order to auto-restart and make your changes available.

Command Line Utilities

Django provides a command line utility that comes with a selection of management commands. One of these runs the development server, while others are used for managing static files and dealing with migrations. Third party apps can enhance the command line utility by offering their own management commands and it can be useful (and easy) to add some of your own. Flask also has a built-in command line utility that uses click which is a mature and robust command line interface toolkit. Just as with Django, it’s possible to add your own custom commands and Flask Extensions can also contribute their own.


Both frameworks offer tools that build upon the built-in python unittest framework to make testing your web application easier. Each has a test client that allows you to easily send test requests to your endpoints and inspect the response to validate correct behavior programmatically. Since both Flask and Django use the built-in python unittest framework, you can swap out default test runners and configure your tests to your preference.

Request Handling

Routes & Views

Both Flask and Django allow you to handle requests by defining views either as a function or a class, and then mapping routes (URL paths) to those views.

By default, Django organizes your request handling logic (views) separately from your routing definition. For each app, you typically define your “url patterns” in a single file that maps each pattern to a view for handling requests that match that url pattern.

An advantage to this method is having a single place in which you can see where a request should be routed. While you can do the same thing in Flask, it’s more common to see the routes declared in the same place as the view, either with a decorator or by explicitly registering the route on the application object (or blueprint if you’re using them).

The following examples of routing the “home/” path illustrate the difference.

In Django:

from django.urls import path

from .views import HomeView

urlpatterns = [
path('home/', HomeView.as_view(), name='home'),

In Flask:

from flask import Flask, render_template

app = Flask(__name__)

def home_view():
Definition of Home View
return render_template("home.html")

When it comes to class-based views, Django begins to differentiate itself by offering a large variety of additional base classes that offer modifiable base implementations for some common patterns you find in web applications. For example, the FormView class bundles the HTTP GET and POST logic for displaying and processing the inputs for a Django Form.

There are a number of these generic views that allow you to build a lot quickly and with minimal code if what you’re building fits the mold.

The Request Object

Both Flask and Django have a “request object” that holds data about the request, but how this object is made available by the framework is pretty different.

In Django, the request object is passed to the view as an argument and must be passed around any time it is needed. The big advantage of this design decision is that the business logic of the application is decoupled from the context of a request. When something needs to be tied to a request context, you’re required to explicitly pass the request object, making it clear where the request context begins and ends. The disadvantage is that whenever you want access to the request it can be cumbersome to have to pass the request object around.

Flask, on the other hand, takes a very different approach and uses a thread-local variable for storing the request. This means that if you want access to the request object, you simply have to import the request object from flask and reference it in your code. The upside with this approach is that you don’t need to pass the request around. If you want it – you just access it. The pretty big downside is that if you aren’t careful, it can be confusing to know when you are in a request context or not. This leads to many new Flask users getting errors about there being no request context when trying to run their code.


For its templating engine, Flask uses an existing tool called Jinja2. This is a very popular templating engine with many features that enable you to build a lot of the static html portions of your website without needing to do too much repetitious work.

Django has its own templating engine that has a very similar syntax and a similar feature set to Jinja 2. In fact, if you prefer to just use Jinja2, it’s simple enough to swap it in as the templating engine of choice.

A description of the differences between Jinja2 and Django’s templating engine can be found here, but to give a sense of the syntax see the following.


{% for item in obj.get_items() %}
{% endfor %}


{% for item in obj.get_items %}
{% endfor %}

Static Files

Keeping track of static files and knowing how to reference them from within your code and templates in a way that supports different environments can be a bit frustrating. To solve this, both frameworks offer utilities for referencing static files so that, based on your configuration, the urls referencing your static files are properly generated for that environment.

Additionally, Django provides a management command for collecting static files from your various apps and putting them wherever your configuration specifies. This comes in handy when it comes to deploying your application in a production environment.

Here is an example of how simple it is to reference static files within templates for each framework.


{% load static %}
<link type="text/css" href="{% static "style.css" %}">


<link type="text/css" href="{{ url_for('static', filename='style.css') }}">


Flask, by nature, was made to be extended. As part of its design is that it specifically avoids offering solutions to things that they feel are application specific and allows for 3rd party and custom extensions that plug right into the application object. You can read up on Flask Extensions here.

Although Django makes more decisions for you, it similarly doesn’t support every eventuality and has a pluggable application structure that allows for a lot of customization and extension. Ultimately, both frameworks have a very rich selection of 3rd party extensions so that chances are, if you need a solution to what seems like a common problem, you’re very likely to find an existing solution.


Through a declarative syntax, Django offers a simple way to define form objects that then allow you to render and process the data in a uniform way. Forms are rendered using built-in templates that can be overridden to customize appearance.

Django’s forms help you handle data validation and security mechanisms such as CSRF protection out of the box so that you do not need to think about it. In Django, there is a special form class (ModelForm) that integrates with the Django ORM Models to make it easy to quickly define forms from your data models.

Flask, however, does not provide any form handling out of the box, but it’s pretty simple to use a package like WTForms, which provides functionality similar to what Django’s forms provide.

Database Support

Object Relational Mapping, Migrations

Django comes packaged with the Django ORM (Object Relational Mapping). This is probably one of the most contentious decisions that Django makes. Some people love the Django ORM for its simplicity and some people hate it – citing shortcomings and its desire to manage the database for you. There’s no doubt, however, that it allows you to get started very quickly and there’s a good amount of power in its simplicity.

The ORM comes packaged with a tool for auto-generating and managing database migrations. Using the provided management commands, you can move rapidly by changing your Django Model definitions and largely database migrations are handled for you: there are a number of situations in which the auto-generated migrations need a helping hand.

The Django ORM is very opinionated and does have some definite limitations, but it can be customized, extended, and ultimately you can resort to raw SQL if you ever have a need to overcome those limitations.

Flask specifically avoids including anything that has to do with database management. The Flask documentation correctly points out that some web applications will not access a database at all.

For the apps that do, there are so many database options out there to choose from that may suit your use-case that it’s better to leave the logic up to others (not the web framework).

If you’re looking to use an ORM with Flask, there are a number of options out there – but if you’re using a relational database, the most popular option would be SQLAlchemy which is far more than an ORM and provides an excellent solution.

Authentication & Permissions

Django comes with an authentication application that integrates vertically with the rest of the system to provide a User model, a permissions system, and support for sessions. There are a number of decisions made in this application that you may or may not agree with, and you’re free to either modify them to suit your needs or to bypass them completely. It’s pretty common, for example, to override the default user model and use one that uses the email as the username.

Out of the box, Flask doesn’t provide a solution for authentication. Your web application may not even have a need for authenticated users. As usual, if you are looking for a way to add user authentication to Flask, there are extensions that can help you to make your life easier. The one building block that Flask does provide here is secure cookies which are handy for implementing an authentication scheme.

Admin Site

Django comes packaged with an admin site that allows you to quickly build an internal tool for managing the data from your data models. When trying to get a web app up and running quickly, the Django Admin is a really easy way to provide a simple interface for managing application data. You can get really far with just a few lines of code, and as your app evolves, you can customize the look and feel of the admin as you like.

Flask doesn’t come packaged with any sort of admin interface, but (no surprise here), the extension Flask-Admin provides something similar to what Django provides – although it is a little more complex to set up since you have to integrate it with whatever authentication scheme you implement.


Both frameworks do their best to set you up well with security protections. Flask’s documentation warns developers to be cautious because no matter what a framework provides, if developers are not careful about how they apply the tools, there can be security vulnerabilities.

From that perspective, since Django does more for you, it handles more of those security concerns as well. Ultimately, however, it really is up to the developer to be careful, read all of the documentation and make educated decisions.


While many will choose one framework over another according to taste, at the end of the day you get used to those differences pretty easily. If you have to decide between these 2 frameworks, take a look at your needs. If your web application will have a need for authenticated users, there are a lot of good decisions that Django makes that will help accelerate your development quite a bit and it’s worth exploring. If you’re pretty opinionated about your database, you don’t want it managed by your web framework, or if you don’t have a database at all, then Django probably doesn’t make much sense for you. Ultimately, you can make a Flask project look very much like a Django project and you can strip down Django so that it looks more like a Flask project, but it’s not necessarily time well spent. So it’s best that you look at the features each has ahead of time. If you need all of the things Django offers and you don’t mind Django managing your database, then it is a really strong option. It’s hard to beat the convenience and speed with which you can build your web app. If you don’t need what Django offers or you dislike the choices it makes, then it makes sense to start with Flask and build your web app in the way you see fit.

How can Kite help?

Regardless of which framework you choose, Kite can help you get going faster. A lot of what you do when setting up a new project is importing and configuring the right components. One of the most annoying things is knowing where to find the various components you want to import. With its intelligent line-of-code completions, Kite helps you save a lot of time when getting started and throughout the development of your application. Download Kite for free to give it a try.