The Flask Mega-Tutorial: Now with Python 3 Support

Posted by
on under

After more than a year working on various projects on the side of my day job, I have now found some time to rest and return to the blog, which I haven't cared for much during this time.

The number one problem I see from my readers is issues when trying to follow my Flask Mega-Tutorial using current versions of Flask, its extensions, or Python 3. In this article I quickly describe the updates I have made to the tutorial.

Announcing the Updated Flask Mega-Tutorial

I'm happy to announce that I have revised all the articles that are part of this tutorial, along with the tutorial's code repository on GitHub. The example code now works with Flask 0.10.1, and all the dependencies were also upgraded to current versions. The example application is now compatible with Python 2.7 and Python 3.3+, and I have also made several changes towards PEP8 compliance, something I did not pay too much attention two years ago when I wrote the original articles.

Migrating microblog to Python 3 required mostly simple syntax updates, but there were a couple of areas that proved tough:

  1. Flask-Babel has problems when used with Flask 0.10 and newer. This is related to a change in how Flask serializes the user session in this version. I have blogged about this separately, since this is likely affecting many projects unrelated to this tutorial.
  2. While testing full text search I have found an issue with the Whoosh package under Python 3. There is a bug report for this problem, but there is no fix yet. I have left support for full text search disabled in Python 3. I will enable it once Whoosh works well with that version.

As far as the content of the tutorials, I decided to stay true to the original articles and not introduce any major changes. That means that for those that are familiar with the tutorial there isn't any significant changes, other than the code will now work with current versions of Python and all the packages. Related to this I think it is important to note the following:

  1. The Database article shows how to track migrations using package sqlalchemy-migrate. Today a lot of people use Alembic instead, many through my own Flask-Migrate extension. I have covered the use of Flask-Migrate and Alembic well in my other tutorials, so I decided to stay with sqlalchemy-migrate for this one. Note that I have updated the version of sqlalchemy-migrate to the current version.
  2. When I wrote the Facelift article the current version of Twitter Bootstrap was 2.3.2. I have not updated the templates to work with current 3.x releases, since that is largely unrelated to the main goal of the tutorial.
  3. Two years ago when I started writing this tutorial the use of blueprints with Flask was new, I did not cover blueprints at all. The training material I did with O'Reilly and my PyCon presentations all have very good coverage of blueprints, so I strongly recommend that you use those to learn about this topic.

In case you have no idea what the topics in this tutorial are, here is the complete list of 18 articles, with links to them:

Recommended Flask Learning Path

I have been very prolific and created several tutorials since I completed the Mega-Tutorial. In this section I want to summarize what I have created and sort it by experience level to help you decide where to start.

Introductory Level

Intermediate Level

Advanced Level

What's Next

In the near future (and until I find a next major project to absorb all my free time) I plan to return to blogging. I have several ideas for new Flask articles, many for topics I originally intended to include in my book, but then had to remove to keep the book from getting larger than originally planned (even though in the end the book ended up having about 100 more pages than the target page count!). Examples of what you can expect to see here in the following weeks:

  • Creating administration interfaces
  • Implementing CORS in Flask APIs
  • Infinite scrolling
  • Single page applications with Flask on the backend

I also expect to write a fair amount of articles related to cloud computing and in particular OpenStack, which is my current focus at work.

Miguel

Become a Patron!

Hello, and thank you for visiting my blog! If you enjoyed this article, please consider supporting my work on this blog on Patreon!

23 comments
  • #1 Andy said

    @Miguel, just wonder! I will follow the Flask Learning Path above. Thank you for your great job for Flask beginner.

  • #2 Jon said

    Thank you in advance for your book and tutorial.
    I rarely, but regularly and definitely, need to build a GUI.
    I've found it expedient - that is, it worked - to mix the HTML in with the control logic, all in Python running as a CGI.

    Surely, this is the poster child for the old days and how not to do it.
    Positives are it's obvious what's going on and it works. Enough about me.
    I'm looking forward to learning about FLASK and this modern world, using your materials.

    Jon

  • #3 Paul said

    I have one quick question Miguel. Why are you such an awesome human being?

  • #4 Mohamed Ali AbElslam said

    very thank's

  • #5 B. A said

    Hello Mr. Grinberg,
    I just got your book and video series on Flask development from O'Reily recently and I'm looking forward to the learning experience. Your Flask Mega-Tutorial seems like a great side project to work upon while I learn Flask Thanks.

  • #6 TheChuckMo said

    Thanks for all the help! - Chuck

  • #7 Marina said

    Can't wait for the tutorial with AngularJS!

  • #8 Miguel Grinberg said

    @Marina: I'm probably going to wait a bit to do anything with Angular, given that the 1.x and 2.x versions are going to be so different. I'm thinking I should probably go with a more stable client-side framework.

  • #9 Daniel said

    +1 for the Infinite scrolling. There is no information about flask+sql alchemy and infinite scrolling in the web/docs.

  • #10 Nicholas said

    Hi Miguel,
    I wanted to use full text whoosh search on my flask application, so I forked whooshalchemy and did a few small fixes for python3. Its on the pypy package index as whooshalchemy3 I think.
    https://github.com/nicholasday/WhooshAlchemy
    Thanks for the tutorials,
    -Nick

  • #11 leasunhy said

    You are awesome!
    I just recommended your tutorials to my friends, who are also flask beginners as me.
    Many thanks!

  • #12 Brijesh said

    Inspired by your tutorial, I have recently started developing yet another blog engine Yapper. But in this, I have tried to integrate it with frontend development also. Its in very early stage but can serve as a good starting point for other developers who want to develop flask-based app.
    Github page: https://github.com/brijeshb42/yapper

  • #13 VD said

    Python Web Development With Flask (one hour long webcast, free)

    This free video is private :(

  • #14 Miguel Grinberg said

    @VD: Yes, sadly O'Reilly has removed the youtube video since I posted this article. Sorry!

  • #15 Dave said

    I am at part 3 of this tutorial and can't get any further because of an error.

    (flask) G:\flask>python run.py
    Traceback (most recent call last):
    File "run.py", line 1, in <module>
    from app import app
    File "G:\flask\app__init__.py", line 6, in <module>
    from app import views
    File "G:\flask\app\views.py", line 3, in <module>
    from .forms import LoginForm
    File "G:\flask\app\forms.py", line 1, in <module>
    from flask.ext.wtf import Form
    File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
    File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
    File "<frozen importlib._bootstrap>", line 1161, in _load_backward_compatible
    File "G:\flask\flask\lib\site-packages\flask\exthook.py", line 62, in load_mod
    ule
    import(realname)
    File "G:\flask\flask\lib\site-packages\flask_wtf__init__.py", line 15, in <mo dule>
    from .form import Form
    File "G:\flask\flask\lib\site-packages\flask_wtf\form.py", line 15, in <module

    from .i18n import translations
    

    File "G:\flask\flask\lib\site-packages\flask_wtf\i18n.py", line 12, in <module

    from flask_babel import get_locale
    

    File "G:\flask\flask\lib\site-packages\flask_babel__init__.py", line 21, in <
    module>
    from babel import dates, numbers, support, Locale
    File "G:\flask\flask\lib\site-packages\babel\dates.py", line 28, in <module>
    from babel.util import UTC, LOCALTZ
    File "G:\flask\flask\lib\site-packages\babel\util.py", line 278, in <module>
    from babel import localtime
    File "G:\flask\flask\lib\site-packages\babel\localtime__init__.py", line 21,
    in <module>
    from babel.localtime._win32 import _get_localzone
    File "G:\flask\flask\lib\site-packages\babel\localtime_win32.py", line 18, in
    <module>
    tz_names = get_global('windows_zone_mapping')
    File "G:\flask\flask\lib\site-packages\babel\core.py", line 58, in get_global
    _global_data = pickle.load(fileobj)
    TypeError: an integer is required (got type str)

    I use Python 3.4.3 on windows 7.

  • #16 Miguel Grinberg said

    @Dave: this is possibly caused by the latest version of Babel, 2.0, released just a few days ago. Try version 1.3 instead.

  • #17 1q84 said

    Hi, I'm in part IV and having (known) problems with migrations.
    I have: python 3.4.3 + sqlalchemy 0.7.9 + sqlalchemy-migrate 0.9.7.
    db_migrate.py works but in ###_migration.py tables from models are not included (I tried it with microblog-version-0.4 from doenload).

  • #18 Miguel Grinberg said

    @1q84: have you made any changes to the models? The download includes the migrations presented in the article, so if you try to trigger a new migration without making any changes to the models an empty migration will be generated.

  • #19 Alex said

    Hi Miguel

    I had the same problem as @Dave "TypeError: an integer is required (got type str)"

    With your solution "flask/Scripts/pip install babel==1.3" I am confirming: It does work now.

  • #20 Dattatreya Mohapatra said

    Dear Miguel,

    After doing everything meticulously, I am getting the following errors:

    Traceback (most recent call last):
    File "run.py", line 1, in <module>
    from app import app
    File "E:\My Files\microblog\app__init__.py", line 6, in <module>
    from app import views
    File "E:\My Files\microblog\app\views.py", line 3, in <module>
    from .forms import LoginForm
    File "E:\My Files\microblog\app\forms.py", line 1, in <module>
    from flask.ext.wtf import Form
    File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
    File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
    File "<frozen importlib._bootstrap>", line 1161, in _load_backward_compatible
    File "E:\My Files\microblog\flask\lib\site-packages\flask\exthook.py", line 62, in load_module
    import(realname)
    File "E:\My Files\microblog\flask\lib\site-packages\flask_wtf__init__.py", line 15, in <module>
    from .form import Form
    File "E:\My Files\microblog\flask\lib\site-packages\flask_wtf\form.py", line 15, in <module>
    from .i18n import translations
    File "E:\My Files\microblog\flask\lib\site-packages\flask_wtf\i18n.py", line 12, in <module>
    from flask_babel import get_locale
    File "E:\My Files\microblog\flask\lib\site-packages\flask_babel__init__.py", line 21, in <module>
    from babel import dates, numbers, support, Locale
    File "E:\My Files\microblog\flask\lib\site-packages\babel\dates.py", line 28, in <module>
    from babel.util import UTC, LOCALTZ
    File "E:\My Files\microblog\flask\lib\site-packages\babel\util.py", line 278, in <module>
    from babel import localtime
    File "E:\My Files\microblog\flask\lib\site-packages\babel\localtime__init__.py", line 21, in <module>
    from babel.localtime._win32 import _get_localzone
    File "E:\My Files\microblog\flask\lib\site-packages\babel\localtime_win32.py", line 18, in <module>
    tz_names = get_global('windows_zone_mapping')
    File "E:\My Files\microblog\flask\lib\site-packages\babel\core.py", line 58, in get_global
    _global_data = pickle.load(fileobj)
    TypeError: an integer is required (got type str)

    Upon looking up "<frozen importlib._bootstrap>" on Google, I found that this is a bug in the Setuptools. Then how come no one else reported the same in comments? Or is there something which I am doing wrong?

    Dattatreya Mohapatra

  • #21 Miguel Grinberg said

    @Dattatreya: try using the version of babel and flask-babel referenced in the requirements.txt file.

  • #22 Condit said

    Hi Miguel,

    Your webcast Python Web Development with Flask at https://www.youtube.com/watch?v=iJmOvssSY7I is no longer available.

  • #23 Miguel Grinberg said

    @Condit: Thanks for letting me know. Apparently O'Reilly made that presentation private now.

Leave a Comment