Django vs Flask vs FastAPI: Full Breakdown & Transcript

I built the same app 3 times | Which Python Framework is best? Django vs Flask vs FastAPI

0h 16m video Published Feb 20, 2022 Transcribed Jul 28, 2026 Patrick Loeber Patrick Loeber
883K views Recent velocity 0.7 views/hour View full performance history β†’

AI Summary

[00:00] which python web framework is the best

[00:02] flask is considered the most popular

[00:03] beginner framework django is the most

[00:05] popular full stack framework offering

[00:07] the most functionality and is used by

[00:09] many companies in production and fast

[00:12] api has only been around for three years

[00:14] but it took the hearts of the python

[00:15] developer community by storm

[00:17] facilitating rapid development and

[00:19] offering a tremendous web app speed when

[00:21] comparing google trends flask is on top

[00:24] closely followed by django but fast api

[00:26] is rising quickly based on github stars

[00:28] django is the winner but also closely

[00:30] followed by flask and fast api catching

[00:33] up quickly and in the speed benchmark

[00:35] test fast api is the clear winner

[00:37] outperforming the other frameworks by a

[00:39] factor of two or even three so which one

[00:41] should you use it's hard to give one

[00:43] clear recommendation because as always

[00:45] the answer depends each framework has

[00:47] its own strengths and weaknesses and all

[00:50] of them are great so in this video i

[00:52] created the same to-do app with all

[00:53] three frameworks in the process you

[00:56] learn how to use each framework and

[00:57] hopefully get a better feel for the

[00:59] trade-offs between each of these so in

[01:01] the end you can make the best choice for

[01:03] your next project the project we are

[01:05] going to build is a simple to do app

[01:07] providing functionality to add update

[01:10] and delete to-do's for each app you'll

[01:12] learn how to use a database use html

[01:14] templates and implement the api routes

[01:17] so let's get started let's start with

[01:19] flask flask is well established in the

[01:21] python community it is loved by

[01:22] beginners and experts for its simple

[01:25] syntax while still being capable of

[01:27] managing full-blown production-ready web

[01:29] apps so let's see how to do it first i

[01:31] recommend to create a virtual

[01:32] environment and then activate it then we

[01:34] need to install flask and also flask sql

[01:37] alchemy to work with a database then we

[01:39] create one file app.pi and import all

[01:42] classes and functions from flask that we

[01:44] need the convention is always to create

[01:46] an app instance with a double underscore

[01:48] name and then creating a route is as

[01:51] simple as defining a function and using

[01:53] the appropriate decorator here we say

[01:56] app.get and then a simple forward slash

[01:58] since this is our home page this would

[02:00] now display hello world on the website

[02:03] in order to use the database we import

[02:05] sql alchemy now we have to set some

[02:08] configuration variables for example the

[02:11] name or path to the database here we

[02:13] simply use a sqlite file and then we

[02:16] create a database instance by using sql

[02:19] alchemy and passing the app to it now we

[02:21] create a model for the database so we

[02:23] create a class to do that inherits from

[02:26] db.model and we give it three columns

[02:28] with the appropriate data type we want

[02:31] an id a title and a complete flag for

[02:34] the to-do item and then we call

[02:36] db.createall to create and initialize

[02:38] our database

[02:40] now of course we want to use this so in

[02:42] the home route we call

[02:44] db.session.query2do to retrieve all

[02:46] to-do items and then we use the render

[02:49] template function from flask with a

[02:51] template file name and the to-do list is

[02:53] additional arguments so that we can use

[02:55] it in the html code of course we need to

[02:58] create the template so we have to create

[03:00] a folder named templates and then a file

[03:02] that we call base.html

[03:04] and here we can use normal html code

[03:07] that displays a form and all to do items

[03:10] now what is special here are these curly

[03:12] braces with percent characters this is

[03:15] special ginger 2 template syntax that

[03:17] basically allows us some python-like

[03:19] logic for example we can have a for loop

[03:22] where we iterate over all to-do's and

[03:24] show the id and title for each to-do

[03:26] then we have an if-else statement to

[03:28] check the complete flag and show the

[03:30] label in a different style and then we

[03:32] also need closing statements for the if

[03:34] and also for the for loop we also create

[03:36] two links that are the buttons to update

[03:39] and delete a to do and the important

[03:41] part is that the ahref points to the

[03:43] update and delete route for this

[03:45] particular to-do id please note that

[03:48] these will be get requests which is not

[03:50] a best practice for updating and

[03:51] deleting data but it works and for

[03:53] simplicity i will use it like this now

[03:55] we go back to the app.pi and can

[03:57] implement the remaining routes first

[04:00] let's create a route to add a new item

[04:02] this has the

[04:03] app.postdecorator since it should be a

[04:06] post request we get the title

[04:08] wirerequest.form and then we create a

[04:10] new to-do item and call

[04:13] and db.session.add.com the changes as

[04:15] last step in here i use the redirect

[04:17] function together with the url4 function

[04:19] to redirect and load the updated home

[04:21] page the update route works similar here

[04:24] we query the particular to-do item with

[04:26] the id remember that we also specified

[04:29] the id in the html code then we update

[04:32] the complete flag commit the changes and

[04:34] again redirect to the home page and the

[04:36] delete route is the very same code

[04:38] except that here we delete the to-do and

[04:40] that's it 49 lines of code is all we

[04:42] need super simple and straightforward

[04:44] this is where flask really shines it

[04:46] won't be that quick with the other two

[04:48] frameworks now to run the app we can

[04:50] export the environment variables flask

[04:52] app equals app.pi and flask n equals

[04:56] development to get hot reloading and

[04:58] then we say flask run to start their

[05:00] development server and now we can add

[05:02] new to-do's update them and also delete

[05:04] them

[05:05] next let's use fast api it's one of the

[05:08] fastest python web frameworks out there

[05:10] right now it also provides an easy

[05:12] syntax allows for rapid development and

[05:14] offers some more nice to have features

[05:16] like automatic interactive documentation

[05:18] and type validation that's why

[05:20] developers love it and it's rising so

[05:22] fast in popularity that i think it will

[05:24] soon catch up with flask and django

[05:26] let's create a new virtual environment

[05:27] for this project then we need to install

[05:30] fast api we also need an asgi server for

[05:33] example uv corn and for the template

[05:36] files and database support we need

[05:38] python multipart sql alchemy and ginger

[05:41] 2. these are essentially the same

[05:43] dependencies as we get with the flask

[05:45] and flask sql installation here we

[05:47] create three files app.pi models.pi and

[05:50] database.pi we need a little bit more

[05:52] code for each compared to flask and we

[05:54] want to maintain a clean project

[05:56] structure the basic app will be very

[05:58] similar to before we import fast api

[06:01] create an app instance and create a

[06:03] function that we decorate with app.get

[06:05] here we return a dictionary which will

[06:08] be automatically converted to a json

[06:10] response one cool thing to mention here

[06:12] is that we could also declare the

[06:14] function as async dev since fast api

[06:16] supports asynchronous programming out of

[06:19] the box and allows for an extremely fast

[06:21] web app but for simplicity i'll stick

[06:23] with a normal function here fast api

[06:26] heavily relies on tie pins so if we want

[06:28] a dynamic route we use this syntax we

[06:31] put the argument in curly braces in the

[06:33] route and then we use the same name as

[06:36] function argument together with a type

[06:38] hint in this case it should be an

[06:39] integer this is concise reduces bugs and

[06:42] gives us automatic type checking which

[06:44] we will see later so let's continue with

[06:47] our to-do app we need a few more imports

[06:49] from fast api we also import a few

[06:52] requirements from starlet this is the

[06:54] asgi framework that fast api is built on

[06:57] top of then we specify our template

[07:00] directory and use a template response in

[07:02] the home function we pass the request as

[07:04] argument and also the database which is

[07:07] a session object that depends on another

[07:09] function don't worry about this syntax

[07:11] yet it will become clear in a moment but

[07:13] note that again for each argument we are

[07:15] using typins here and then again we

[07:17] query the database for all to do's and

[07:20] return a template response that needs

[07:22] the html file the request and the to-do

[07:24] list in this case the arguments for the

[07:27] template file are passed as dictionary

[07:29] now we also create a template directory

[07:31] and the base.html file and here we can

[07:34] use the exact same code as before since

[07:36] we are also using ginger 2 templating

[07:39] syntax now let's set up the database we

[07:41] get the imports and set up the path to

[07:43] the sqlite database then we need to

[07:45] create an engine we also need to create

[07:48] a session instance and lastly we declare

[07:50] the base class from which the model will

[07:52] inherit in the next step for the model

[07:54] we import the database and this base

[07:56] class we just declared and then we

[07:58] create a to-do class that looks very

[08:00] similar to the one from the flask app

[08:02] but now we inherit from base then we

[08:04] define a table name and use the same

[08:07] fields as before now we can go back to

[08:09] app.pi and make use of all of this we

[08:12] import the session class so we can use

[08:14] it as type hint we import the models the

[08:16] session local object and the engine then

[08:19] we create all database tables and then

[08:21] we create a helper function to access

[08:23] the data by session this will now be

[08:25] passed to the home function as a

[08:27] dependency which means if the database

[08:30] cannot be accessed then also the request

[08:32] to this route throws an error and this

[08:34] is already handled for us by fast api so

[08:37] you can see we need a little bit more

[08:39] code here but in return we get a lot

[08:41] more functionality already and a safer

[08:44] code now inside the function we can use

[08:47] the session object and query the

[08:48] database with the same syntax as in the

[08:50] flask app let's continue and add the add

[08:53] route which must be a post request

[08:56] as parameter we also use the request and

[08:58] the database and now as new argument we

[09:01] also put in the title which is a string

[09:04] that comes from the form and then again

[09:06] we create a new to-do added to the

[09:08] database and commit the change and then

[09:10] i get the url of the home page and

[09:12] return a redirect response i also

[09:14] specify a particular status code which

[09:17] is needed because we now change from a

[09:19] post route to a get route very similar

[09:21] we now add the update route and as

[09:23] mentioned before we use the to do id as

[09:26] dynamic argument with a tie hint then we

[09:28] query the to do change the complete flag

[09:31] commit the change and again redirect to

[09:33] the home page and finally we use the

[09:35] same code for the delete route but here

[09:37] we delete the to-do item and that's it

[09:39] we can now start a server by saying

[09:41] uvicorn app colon app the first is the

[09:44] file name and the second is the app

[09:46] instance we also use minus minus reload

[09:49] while we are in development mode and

[09:50] then we can go to this address and have

[09:52] a working to-do app one more cool

[09:54] feature we also get out of the box with

[09:57] fast api is automatic api documentation

[10:00] so we can go to the slash docs route and

[10:03] here we see all the different api

[10:05] endpoints together with the type for

[10:07] example we can click on the add post

[10:10] endpoint and then we see more details

[10:12] like that it needs a title as string we

[10:14] can also try this out enter a title and

[10:17] execute the command and then we can

[10:19] inspect the result so here we see we get

[10:21] the response code 200 so all is good and

[10:24] we see the raw template response that is

[10:26] visible on the page we could also try

[10:29] another route so let's test the update

[10:31] route this needs a to-do id as integer

[10:34] so if we try to send a string here then

[10:36] it wouldn't let us and on the page we

[10:38] would see an error code and again all of

[10:41] this is handled for us by fast api and

[10:44] this is possible because we used the tie

[10:46] pins all right and that's the to-do app

[10:48] with fast api i hope i could demonstrate

[10:50] some of the cool features here now for

[10:52] the final app we use django while flask

[10:54] and fast api are considered to be more

[10:57] like a micro framework change is a full

[10:59] stack framework with many batteries

[11:01] included it's the backend framework of

[11:03] choice for many fortune 500 companies

[11:05] while the learning curve might be

[11:06] steeper than with the others it offers

[11:09] so many features that it makes your life

[11:11] easier once you know your way around it

[11:13] again i start by creating and activating

[11:15] a virtual environment then we only need

[11:17] to say pip install django this comes

[11:19] with all the requirements that we need

[11:21] now we say changu admin start project

[11:24] and give it the name to do app this

[11:26] creates a new folder and inside the

[11:28] folder we have the manage.py file and

[11:31] another subfolder with the same name and

[11:33] all the starter files we need we cd into

[11:36] the first folder and can run python

[11:38] manage.pi run server this starts the

[11:41] server and we have the initial app up

[11:43] and running for now we quit the server

[11:45] again and say python manage.pi start app

[11:48] and the name to do list an app is a

[11:51] component inside a project that is

[11:53] responsible for certain things like here

[11:55] for managing the to-dos in this simple

[11:58] project this is the only app we need but

[12:00] imagine if we add authentication then we

[12:03] could put this in another app to keep

[12:05] the logic separate and clean after

[12:07] creating an app we also need to add the

[12:09] app name to the installed apps in the

[12:11] settings.py file now we want to add the

[12:14] views so inside to do list.views pi we

[12:18] add a function that gets a request and

[12:20] then we return the render function with

[12:22] a template name and this dictionary all

[12:24] items we want to pass the missing to-do

[12:27] part will be implemented in a moment for

[12:29] each view we need to register a url so

[12:32] we create a urls.pi file inside the

[12:35] to-do-list folder import the path

[12:37] function the views module and then we

[12:39] define all url patterns we want to add

[12:42] in this case we leave the route of the

[12:44] path empty since this is our home page

[12:47] and then we use the corresponding

[12:48] function and can also give it a name now

[12:50] we go to the to do app.urls.pi

[12:54] and use the include function to include

[12:56] all urls from the to do list app you can

[12:59] see that there already exists an admin

[13:01] path this is because django gives us an

[13:03] admin panel out of the box which we will

[13:05] see in a moment now we will need to

[13:07] create the template file so let's create

[13:09] a new templates folder in the top

[13:11] directory and then we again create the

[13:13] base html file and put in the same code

[13:16] django uses its own templating language

[13:19] which is similar but slightly different

[13:21] than the ginger 2 template but in this

[13:23] case we only have a for loop and an if

[13:26] statement and this is actually the very

[13:28] same syntax but there is one thing we

[13:30] need to change in the form part we need

[13:32] to add the csrf token this is a security

[13:36] mechanism that prevents attacks to the

[13:38] form but we don't need to do more than

[13:40] adding this here now we need to go back

[13:42] to the settings.py and add the templates

[13:45] folder to the directories key now we

[13:47] implement the model class so inside the

[13:49] to-do list models.py we create a class

[13:52] that inherits from models.model and then

[13:55] we again create the same fields with the

[13:57] correct data type and we also implement

[13:59] the string method to see an accurate

[14:01] description here we don't need to create

[14:03] an id since django does this for us now

[14:06] in the console we say python manage.pi

[14:09] make migrations followed by

[14:11] pythonmanage.pi migrate then we also

[14:14] create a super user because i want to

[14:16] show you the admin panel so we say

[14:18] python manage pi create super user we

[14:21] follow the instructions and put in a

[14:23] name and email and the password as next

[14:25] step we go to the admin.py and register

[14:28] the to-do model and now we go back to

[14:31] the views.pi import the to-do class and

[14:34] then query all to-do's in the index

[14:36] function let's run the server again and

[14:38] test this we see the home page with zero

[14:41] to-do's for now if we click on the add

[14:43] button we get an error since we haven't

[14:45] implemented this view yet but one cool

[14:47] feature that is already available is the

[14:49] admin panel so if we go to the slash

[14:52] admin route we can log in with the super

[14:54] user we created and here we can see

[14:57] different groups and users if we would

[14:59] add authentication we also see the to-do

[15:01] models with all the fields we specified

[15:04] and here we can interact with our

[15:06] database so we could add or modify the

[15:08] database entries right from the admin

[15:10] panel this is one very cool built-in

[15:13] feature that you don't get with the

[15:14] other frameworks so now let's log out

[15:17] again and implement the missing views so

[15:19] we import two more functions and then

[15:22] implement the add route we require that

[15:24] this should be a post method by using

[15:26] this decorator we could also check the

[15:29] type of the request inside the function

[15:31] but i wanted to show you this second way

[15:33] of doing it inside the function we then

[15:35] create and save a new to-do and redirect

[15:38] to the index page now we implement the

[15:40] update function this gets an additional

[15:43] parameter to do id which is then be used

[15:46] to query for this to do and then we

[15:48] change the complete flag and save it and

[15:50] again redirect the syntax for working

[15:52] with django models is slightly different

[15:55] than before but in my opinion it's even

[15:57] more simple and straightforward and the

[15:59] last view we need is the delete view

[16:01] which is very similar but here we delete

[16:03] the to do and now we only need to add

[16:05] all these views to the urls.py

[16:08] so in here we add all the paths with the

[16:10] corresponding route and view function we

[16:13] can use this syntax with a data type and

[16:16] parameter name to add dynamic views and

[16:18] that's it we can now go back to our app

[16:21] and we should be able to add new to-do's

[16:23] and then update and delete them awesome

[16:26] alright that's it you can find the code

[16:28] for all apps on github the link is in

[16:29] the description this video was a lot of

[16:31] work so if you enjoyed it please hit the

[16:33] like button i'm also interested to hear

[16:35] what's your favorite framework so please

[16:37] leave me a comment below and as always i

[16:39] hope to see you in the next video bye

More from Patrick Loeber

View all

⚑ Saved you 0h 16m reading this? Transcribe any YouTube video for free β€” no signup needed.