Flask vs. Django: Why Flask Might Be Better
Flask and Django are two of the most popular web frameworks for Python (although there are many more). In this post, I'll discuss some of the points you should consider when you're choosing between Flask and Django. We'll also walk through a "Hello, World" app in each of them to get more of a hands-on feel for how they work.
(Note: I'm a long-time Flask user and author of the book Flask by Example, so I'm personally a bit biased towards Flask. I'll keep this overview as objective as possible though).
Wait, why do I need a web framework and what is it anyway.
When you first started developing Python applications, you probably developed so-called "command line applications". The user has to run these scripts in a shell or command prompt and pass input as arguments or through standard input. Several years ago, the natural progression from building these kind of applications was to build desktop applications — a program that allows users to interact using a mouse and keyboard, which contains menus and other interactive elements. These days, it's more common to transition into building web applications — your users will interact with your program via their web browser. For a nice overview of why web applications are arguably better than desktop applications, see Patrick "patio11" McKenzie's post here: http://www.kalzumeus.com/2009/09/05/desktop-aps-versus-web-apps/.
If you decide you want to build a web application, and you would like to develop it in Python, you'll probably want a so-called web framework. There are a lot of repetitive and boring parts of building backend logic, user interface, and hooking everything up to the Internet so that users can navigate your app in their browser. A web framework aims to implement all the functionality common to most web applications, such as mapping URLs to chunks of Python code.
Exactly what is implemented in the framework and what is left for the application developer to write varies from framework to framework. The biggest difference between Flask and Django is:
- Flask implements a bare-minimum and leaves the bells and whistles to add-ons or to the developer
- Django follows a "batteries included" philosophy and gives you a lot more out of the box.
We will now discuss their differences in more detail.
Quick Comparison
If you're here for quick answers, this section is for you!
- Main contrasts:
- Flask provides simplicity, flexibility and fine-grained control. It is unopinionated (it lets you decide how you want to implement things).
- Django provides an all-inclusive experience: you get an admin panel, database interfaces, an ORM, and directory structure for your apps and projects out of the box.
- You should probably choose:
- Flask, if you're focused on the experience and learning opportunities, or if you want more control about which components to use (such as what databases you want to use and how you want to interact with them).
- Django, if you're focused on the final product. Especially if you're working on a straight-forward application such as a news site, an e-store, or blog, and you want there to always be a single, obvious way of doing things.
- More information:
- Django has been around for longer — it was first released in 2005, while Flask debuted in 2010 — and is more popular — in January 2017, there were 2631 StackOverflow questions about Django and 575 for Flask. Both frameworks are growing steadily in popularity, as can be seen by the number of StackOverflow questions about each in the image below.
- Flask has a much lighter footprint, comprising under 10000 source lines of code to Django's approximately 240000 lines.
- Django has been around for longer — it was first released in 2005, while Flask debuted in 2010 — and is more popular — in January 2017, there were 2631 StackOverflow questions about Django and 575 for Flask. Both frameworks are growing steadily in popularity, as can be seen by the number of StackOverflow questions about each in the image below.
Hello, World!
The first thing people usually do when they're learning a new technology is to follow the simplest set of steps that produces the output "Hello, World!" Below, we will go over the steps to build a "Hello World" applications with Flask and Django.
Note that Flask, which is focused on simplicity and minimalism, allows us to get "Hello World" running much faster, but this should not be taken to mean that Flask is the superior framework. It would probably take less time and effort to get a more sophisticated web application (such as one that handles and validates user input and stores this in a database) running in Django than in Flask. However, seeing the two Hello World projects will give us a better feel for the two frameworks, and it will allow us to describe some of their inner workings along the way.
Flask
The first thing we need to do in order to use Flask is to install it. This can easily be done by using pip. Depending on how your pip is set up, and which version of Python you usually use, you may not need the 3 or the --user flag in the command below.
pip3 install flask --user
Once you've done that, create a Python file called flaskhello.py and insert the following code:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
if __name__ == "__main__":
app.run()
Let's break down what this code does:
- Line 1 imports Flask
- Line 3 initializes an
appvariable, using the__name__attribute - Line 5 is where the magic of Flask happens. The
@app.routeis a Python decorator. It takes the function directly below it and modifies it. In this case, we use this to route traffic from a specific URL to the function directly below. Using different@app.routecalls, we can 'trigger' different parts of the code when the user visits different parts of our application. In this case, we only have a single route/, which is the default "root" of our application. - In Line 6 the function name
hellois not important. In stead of calling this function from somewhere else in our code, it will be called automatically. It's still a good practice to give it a relevant name though. - Line 7 returns the string to our user. Usually we would render a template or return HTML here so that users will see a nicely formatted page, but returning a Python string works fine too.
- Line 9 is normal Python boilerplate to make sure we don't run anything automatically if our code is imported by another Python script.
- Line 10 calls the
run()method of theappwe initialized in Line 3. This starts the development server for Flask and allows us to visit our web application from our local machine by visiting localhost.
You can now run the command python3 flaskhello.py and you should see output similar to:
>>> Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
In the message above, '5000' is the port number that our Application is running on (yours might be different, e.g. '5003') and '127.0.0.1' means that the application is running on local host — it's only accessible on our development machine. If you open a web browser and visit http://127.0.0.1:5000/ (substituting the port number if necessary), you'll see a web page that returns the "Hello, World!" greeting.
Django
Django can also be installed through pip. Run the following command:
pip3 install django --user
Once it's installed, we need to run some Django scripts to create a project in order to create an app. When you installed Django, it also set up the django-admin command, which we'll use now. Run the following:
django-admin startproject hellodjango
This creates a new Django "project," and will create the hellodjango directory in the location where you ran the command. If you look in the hellodjango directory, you'll see that it created a manage.py file and a subdirectory which is also called hellodjango. Inside the subdirectory there are three Python scripts. We'll only need to worry about urls.py for our "Hello World" project.
The next step is to use Django to create an App, which is an organizational structure below that of a Django Project (one Project can contain many apps). We will use the manage.py file that the previous command created in order to create the application. From the outer hellodjango directory, run the following command:
python3 manage.py startapp helloworld
This creates the helloworld app and makes it part of our hellodjango project. Now we need to configure the URL routing (like we did with @app.route in Flask). Because Django projects have more default structure than Flask apps, we'll have a few extra steps. The previous command created a helloworld directory within the outer hellodjango directory. Open the automatically created helloworld/views.py file and add the following code:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, World!")
- Line 1 imports the
HttpResponsefunction, which we can use to send a string over HTTP to the user of our web app. As with Flask, we wouldn't usually use this, as we'd want to do more complicated things with rendering HTML templates. However, for our Hello World app this is all we need. - In line 3, we're defining an index function. Here, unlike with Flask, we don't use a decorator that says this function should be called when the user visits our application. Instead, we'll set this up via two
urls.pyfiles — one for the project, which was automatically created, and one for the application, which we'll need to create. - Line 4 returns the "Hello, World!" string wrapped in an HttpResponse so that it can be displayed in our user's web browser.
Now we need to create a urls.py file for our application. Create helloworld/urls.py and add the following code:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
- Line 1 imports the
urlfunction so that we can link specific URLs to functions in ourviews.pyfile. - Line 3 imports the
views.pyfile that we added our "Hello, World"index()view to. - Lines 5-7 sets up a list of
urlpatterns— this is equivalent to the@app.routedecorators that we used in Flask. We match specific URLs using regular expressions, and link these to functions in ourviews.pyscript. In this case, we set up a single pattern, which matches an empty URL (like "/" in Flask — in other words, the default page of our application) and links it to theviews.indexfunction that we wrote earlier.
That's the URL configuration for our app (helloworld). We also need a URL configuration for our project (hellodjango). Edit the hellodjango/hellodjango/urls.py file, which was automatically created (it might be a bit confusing that there are two urls.py files, but it should make sense if you think of one belonging to the entire project, routing URLs to different apps, and the other belonging to the helloworld app alone). Add the following code:
from django.conf.urls import include, url
urlpatterns = [
url(r'^hello/', include('helloworld.urls')),
]
This is similar to the previous file. However, instead of routing URLs of a specific pattern to a specific view, we are routing them to a specific application. In this case, any URL that has /hello after it will be sent along to our helloworld application and will look in helloworld.urls to work out which view to call.
Now go back to the outer /hellodjango directory (the one which contains the manage.py file) and run the following command:
python3 manage.py runserver
This runs the Django development server, which lets us visit our application on localhost, as we did with Flask. You should see output that is similar to the following:
Performing system checks...
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
February 03, 2017 - 16:14:20
Django version 1.10.5, using settings 'hellodjango.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
You can ignore the warning about the migrations — this is related to the database for the web application, which we are not using. The important line is line 10, which, similarly to Flask, tells you which port the server is running on. In the example above, it is 8000, so we can visit http://127.0.0.1:8000/hello to view our "Hello, World!" greeting (don't forget the /hello at the end, which tells Django which app to visit).
Final Remarks
In this post, I provided an introduction to Flask and Django, followed by a short comparison of the two, and then proceeded to show how to build a "Hello World" app using each framework.
Django is a heavier framework than Flask — if you're learning web programming, it can be harder to figure out which pieces are responsible for what functionality, and what you need to change to get the results that you want. However, once you get used to Django, the extra work it does can be really useful and can save you time in setting up repetitive, boring components of a web application.
It's sometimes difficult to choose between the two frameworks — the nice thing is that even when you get into their more advanced functionality, such as templates, the two remain very similar in many aspects (many job advertisements ask for "Django or Flask experience" as a result). It's therefore easy to switch from one to the other if you ever need to or want to.
If you're still in doubt as to which framework to use after reading this guide, I would recommend that you go with Flask — you'll figure out how the pieces fit together more easily, and you'll never have functionality lying around that you're not actually using.
Overall, if we have to make a choice of Django vs Flask, I almost always chooses Django. It is a solid framework, great for launching apps for everyone - from startups to big companies; it excels at implementing Python possibilities and provides all the tools needed for sufficient app operations. Quite opposite, Flask works more like a sandbox for developers, where they can hone their skills and quickly test solutions using different modules and libraries. We prefer using it for testing and working on less-structured objects, while using Django to deliver a solid product, meeting and exceeding customer’s expectations. I’d like to share some facts about it https://goo.gl/WJzgI1
Hi Gareth! I wanna build a web app, kinda like this site (https://ensmo.com/) but just the Data Analysis Simplified part. What framework should I use? Flask or Django? I just finished learning basic Flask and going to learn some basic Django so I can compare them myself. But I really need an expert opinion on this. Thanks before!
I do a lot of Python mentoring, and I mostly agree with your points. I think there are more points worth making. Because Flask requires you to set up basic components like auth and the database yourself, there is a real risk of doing it insecurely or inefficiently. Similarly, because Flask is far less structured, it gives novice developers a lot of space to get themselves into trouble. Personally, I prefer starting people on a more structured and dogmatic framework like Django, and moving to a more flexible framework like Flask only when they are experienced enough to a) know which framework is better for a specific task and b) set it up well. I don’t think there is a clear answer in the long-standing developer debate about how much of the underlying structure developers need to understand. To use an analogy, we definitely need car mechanics, but not everyone needs to know how to fix a car in order to benefit greatly from being able to drive around. I try to tailor my mentoring to a person’s specific needs.
I’ve yet to see a project where choosing Flask over Django makes a lot of sense. Flask is usually advertised as being simpler. But being simpler, doesn’t mean that it’s simpler to utilize, simpler to build a sane project out of.
For hello worlds and similar, very-very simplistic projects Flask might be simpler, given that you don’t already know Django(!). However, for any meaningful project, you’ll end up adding quite a lot of functionality that you have in Django. And it means that you have to figure out how to do a lot of things, exactly because Flask is ‘unopionated’ (which doesn’t mean that the plugins you use are also that, BTW). Now to build a sane project from a lot of small lego pieces, you indeed need more experience, not less, than using an opinionated framework.
At first I thought that django was pretty bad for not having you replace crucial parts of it. Mainly the templating engine, which is replaceable by now, btw, and the ORM. (Especially since the java frameworks I have looked at before would allow you to do that without any problem, mostly thanks to the standardized APIs.) But it turns out, that most of the time you don’t need it. Also, quite a lot of pieces are changeable (e.g. the admin app, that you mention is one of those things, and you don’t have to use it anyway).
Also, Django does not enforce a directory structure on you. You can configure things pretty freely, and indeed the default layout is pretty much unusable for any serious project. The fixed structure is so much untrue, that django even has a mechanism for generating the project structure from a template you provide. (Though it’s pretty rudimentary and better to use cookie-cutter.) And while I like that it’s not enforced, I don’t like that you don’t get a sane default, so everyone has to discover something usable for themselves, which end up being pretty similar anyway.
Both are great tools. To make a car building analogy, I feel like Django is a kit you that comes with all of the parts included in the box, whereas Flask is only a chassis and you need to pick out all of the parts like engine, transmission, wheels, etc. Django is great but if you really want to pimp your ride out with customizations Flask is the way to roll but you’ll need an understanding of all of the components and inner workings to put it all together.
Flask is awesome and pretty much what I always use. The design philosophy is similar to Unix’s in that it incorporates small, modular, components, which I like. The biggest draw for me to Django is the admin UI. Being able to deliver a backend for free is pretty awesome, especially when deadlines are tight.