Flask Mega-Tutorial Update: Flask 2.0 and more!

I'm excited to share that I've completed a revision of the Flask Mega-Tutorial to keep it in line with new releases of Flask, Python and third-party dependencies.

Flask Mega-Tutorial

To celebrate this update, you can purchase the paid version of this course with a $10 USD discount (this offer is valid through the rest of July 2021). If you are interested in this offer, use the FLASK2 promotional code at checkout, or click here to go directly to the order page with the coupon added. Thank you!

What's in this Update?

While I've made changes in every chapter, below is a list of some of the most interesting updates:

  • Tested to work well with the new Flask 2 release (as well as remaining compatible with Flask 1.x releases)
  • Tested to work well with the 3.6, 3.7, 3.8 and 3.9 releases of Python.
  • All dependencies upgraded to their latest official versions.
  • The updated code has been pushed to the GitHub repository.
  • The FLASK_DEBUG environment variable was replaced with the more modern FLASK_ENV.
  • The importance of the .flaskenv file is more clearly stated.
  • Recommend SendGrid as an alternative email service with a decent free email sending quota.
  • Fixed backwards incompatible changes in the pyjwt package.
  • Switched to the langdetect package for language detection.
  • Upgraded Ubuntu to 20.04 in Linux deployment chapter.
  • Addressed issues with Heroku's Postgres database and SQLAlchemy 1.4.
  • Solved issues with recent releases of the pymysql package requiring the cryptography package to be installed as well.

There is one aspect of the tutorial that is still in need of an update: the use of the Flask-Bootstrap extension. Unfortunately this extension has not been updated in a long time, and it continues to require version 3 of the Bootstrap CSS framework, which is now two major releases old. While there are a few forks of Flask-Bootstrap that implemented support for Bootstrap 4, there are currently none that I know of that support Bootstrap 5. Out of the Bootstrap 4 forks, most are already unmaintained, or else they don't have a clear path to Bootstrap 5. Given that there are no worthy successors to Flask-Bootstrap, I have decided to continue using this old version, which continues to work well, with the caveat that it keeps the user interface stuck on Bootstrap 3. I will continue to monitor this and update the Bootstrap chapter when a good alternative to Flask-Bootstrap appears.

How to Get this Update

The update to the tutorial is available right now on this blog. This continues to be freely available to everyone.

If you have purchased the paid version from my Courses page, first of all thank you so much for your support, and second, you can find the updated ebook downloads and text of the tutorial in your course page. Note that most of the updates are minor in nature, so at this time I have not made updates to the video material.


  • #26 Kerem NAYMAN said 2021-09-10T15:20:16Z

    Hello, Miguel, I've seen Flask has a support for ASGI via asgiref: https://flask.palletsprojects.com/en/2.0.x/deploying/asgi/ Using this method, can we have a full async web app with Flask?

  • #27 Miguel Grinberg said 2021-09-11T11:51:09Z

    @Kerem: No. With that method the Flask application runs inside an executor, it does not run asynchronously.

  • #28 Roland said 2022-01-07T17:29:48Z


    Thanks for the Mega Tutorial ebook and the course

    One question about chapter 5, listing 5.11 Shouldn't at least the variables user and posts be passed instead of the user template argument? I get a NameErrror respectiy an interal server error, if I don't do so and simply remove the templates .

  • #29 Miguel Grinberg said 2022-01-08T11:00:33Z

    @Roland: the user is not needed because it is obtained from the current_user variable. You may be missing some changes, so please review your code and compare it against mine to find what you did wrong.

  • #30 Michael said 2022-03-14T12:23:17Z

    Hi @Miguel, this update looks great ! Bootstrap 5 is now supported by "bootstrap-flask" (https://github.com/greyli/bootstrap-flask). Is there a plan to update relatively soon the tutorial to include it ?

  • #31 Miguel Grinberg said 2022-03-14T15:07:02Z

    @Michael: I'm not planning to make an update in the near future. The Bootstrap-Flask extension has some important differences compared to the original Flask-Bootstrap and is more complex, so it would take more than a simple search/replace job to switch. Honestly, if I had to write a project with Bootstrap today I would not use an extension. When I decide to do another refresh I'll probably remove Flask-Bootstrap and use Bootstrap 5 directly.

  • #32 Steve Nicholson said 2022-06-12T05:49:16Z

    Hi, Miguel. I bought the Flask Mega-Tutorial. It has been indispensable as I work to develop a practice management system for my wife's new veterinary acupuncture clinic.

    Have you looked at bootstrap-flask (https://bootstrap-flask.readthedocs.io) as a replacement for flask-bootstrap? It's under active development and has support for Bootstrap 5 as of January. It's working well in my initial trials.

  • #33 Miguel Grinberg said 2022-06-12T13:32:41Z

    @Steve: I have answered this question already. See the comment above yours.

  • #34 Charles U. said 2022-09-04T00:47:01Z

    Hello Mr. Miguel, firstly, thank you so much for your really good books, they have really helped me on my Flask journey, however I have been experiencing a challenge for weeks now without a solution, I know you are a very busy person but I do hope you can find sometime in your very busy schedule to point me in the right direction as this means everything to me. Using your book and github repo, I implemented a decorator similar to this - https://github.com/miguelgrinberg/flasky/blob/master/app/decorators.py however I keep getting the error message below;

    if not current_user.can(permission):

    AttributeError: 'NoneType' object has no attribute 'can'

  • #35 Miguel Grinberg said 2022-09-04T10:52:11Z

    @Charles: the problem is that your current_user variable is set to None and not to a user. I have no way to know what this is the case, you will need to debug your application to find out what this variable is incorrectly set.

Leave a Comment