Hacker News new | past | comments | ask | show | jobs | submit login
The Flask Mega-Tutorial (miguelgrinberg.com)
243 points by giis on March 24, 2013 | hide | past | favorite | 56 comments



> If you are on Linux, OS X or Cygwin, install flask and extensions by entering the following commands, one after another

I think this is a really bad advice. Instead create a file called requirements.txt and add the required livraries, one per line.

Then you can install it with

    flask/bin/pip install - r requirements.txt
Edit: More information in the documentation[0]

[0]: http://www.pip-installer.org/en/latest/requirements.html


You can always regularise things after with:

    pip freeze > requirements.txt


Or with:

  pip freeze -r requirements.txt
So you can keep your file structure with comments, nicely separating your dependencies from the dependencies of your dependencies. This way you'll have a much nicer time the day you need to remove one of them :)

And beware of git urls being replaced by egg names in the process.


I prefer keeping routes in a separate file.

Instead of

    @app.route('/')
    def index():
        pass
I keep a routes array

    routes = [
        ('/', endpoint='index', view_func=index)
        ...
    ]
I find it a lot pleasant to look up all routes at the same place rather than guessing or searching. Also, I give an explicit name to all endpoints.

I do the same with blueprints. Blueprints have their own urls.py, and blueprints don't specify the url prefix. For eg, a comment blueprint will define '/', rather than '/comments'. I leave the url prefix to the main application.

    app.register_blueprint(comment, url_prefix='/comment')
For migrations, I prefer alembic to sql migrations - https://alembic.readthedocs.org/en/latest/tutorial.html I find Alembic simpler than SQLAlchemy(without compromising on power). Alembic can autogenerate migrations based on your model definitions. The way I work is I add a new model, and then run alembic to autogenerate the migration. Same goes for altering models.

For settings, I maintain setting.py, dev_settings.py, prod_settings.py. settings.py contains all the common settings. If environment is not defined, I do a `from dev_settings import *`, else I do a relevant import for the environment.

I also prefer having BEFORE_REQUESTS, AFTER_REQUESTS, MIDDLEWARES, LOG_HANDLERS, TEMPLATE_FILTERS, CONTEXT_PROCESSORS, ERROR_HANDLERS... in settings, and in main.py, call the relevant functions. That way, I don't have to hunt down the codebase. For blueprints, I define the same variables in __init__.py.

Model forms are another time saver(use wtforms, or preferably flask-wtform)

    from flask.ext.wtf import Form
    from wtforms.ext.sqlalchemy.orm import model_form
    import models


    PostForm = model_form(models.Post, models.db.session, Form, field_args = {
        'name': {'validators': []},
        'title': {'validators': []},
        'content': {'validators': []},
    })
models.Post is flask-sqlalchemy model, models.db.session is sqlalcheymy session. You don't need to list all model fields for your model form. I find keeping models and forms in sync a pain. This way, I only keep the validations in sync(field_args isn't required - that's an example of adding validations).

I use flask-debugtoolbar for basic profiling and debugging. flask-webassets is awesome for managing assets and dynamic compilation. flask-script for writing manage.py jobs(python manage.py get_deps, python manage.py db_createall etc etc)


Sounds an awful lot like django the way you're using flask


I use both Flask and Django(and Sinatra and Rails). I tend to like Flask more than Django. It's just that big applications tend to have similar structure.

Armin have done a great job with Flask. The framework is quite malleable. I have written both 1 file flask app with inline routes, as well as 'bake-my-own-framework' flask apps. I believe that's a good thing.


That pattern is pretty common in general, no? I use the same url dispatch array in Tornado projects.


But with SQLAlchemy instead of Django's relatively poor ORM.


On the routes side it also means you don't fact around having to import a module to get your app - if you can instantiate the app (as it were) and then set up routes you can create a factory much more easily and pass it around with little worries - but anchored to a module import as in the docs is less than helpful

Would love to see or hear more about your default setups though. Is there an example in OSS?


I don't have something clean, but I pushed a demo https://github.com/rahulkmr/flask-bigapp-template

The focus points are:

1. Routes in a separate file. Check config/urls.py

2. Blueprints are level of abstraction. Check blueprints/post. It's a simple blogging app. Blueprints have their own forms, models, urls, views.

3. Add blueprints to the app under config/blueprints.py You can mount the blueprint at '/' or an url prefix viz '/posts'

4. Blueprints define their own hooks. Check blueprints/post/__init__.py for an example.

5. Schema migration using alembic. Write your model:

    class Post(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))
        title = db.Column(db.String(200))
        content = db.Column(db.Text)

        def __init__(self, name, title, content):
            self.name = name
            self.title = title
            self.content = content
Save your file and add the blueprint to config/blueprints.py(if it's a blueprint), and run:

    alembic revision --autogenerate -m "Create post table."
Check the generated schema in migrate/versions/ Tweak the migration and then `alembic upgrade head`

6. Flask-WTF and wtforms in general used for validation.

7. settings.py used for hooks. See config/settings.py and main.py

main.py is the glue. The code is quite simple as it doesn't do much. Ignore manage.py. That's my personal scaffold generator(like rails). Also ignore the custom template formats. That again is my personal slimish jinja templates.

I use some variation of this template in my projects. This is just guidelines. You can modify it to your heart's content to suit your needs.


That's a great point. I think I will start using that method for defining routes, myself.


Once you construct your routes list, what do you do with it? Do you iterate over it with app.add_url_rule?


Yes. I have a main.py which reads the toplevel urls.py and all blueprints urls.py, and sets the routes.

https://github.com/rahulkmr/flask-bigapp-template


The biggest problem I have with Python frameworks is the fact that it's hard (at least for me) to configure server and just write aplications. I came from PHP background, where you install few packages, configure apache/nginx (which is quite fast) and things just work. I'm learning python for some time now, but I still can't create working python environment... I know django basics, and use its server for developing, but I don't know how to configure nginx on my VPS so I can have multiple python webapps (my simple apps, django apps, flask etc.). Someone has good resources for that (believe me, I read a lot of tutorials)?


Since most Python frameworks are just WSGI application (except when you go Tornado or Twisted route), you can easily apply deployment instruction for one framework with others. I've found Deploying Flask to be a good tutorial on how to deploy WSGI application:

http://flask.pocoo.org/docs/deploying/

There's also uWSGI, which is possibly the most underrated deployment option in Python world but Nginx has native support for it (and its documentation is pretty good nowadays):

http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.h...

Edit: all -> most


Not all Python web frameworks use WSGI. (e.g. Tornado).


Well, true. Let's change that to "most". :-)


It's the docs are poor, the actual procedure is very easy.

Eg. if you installed php on apache, your process may be to apt-get or build from source a mod_php then get the relevant LoadModule line into your apache config.

For python you'd do the same, except you'd use mod_wsgi instead of php.

Part of the problem with python is there are so many ways to achieve the same thing. No doubt others are reading this and thinking "no, you should do x" - hell i'm feeling that myself as i type! This highlights the fact there just is:

    1) Too little documentation
    2) Too little info on what approaches work best in what situations


I haven't yet deployed a big app with flask yet, but for my "playground" (Intranet App, very low load) I use Gunicorn (http://gunicorn.org/ ), which is extremely easy to set-up. For a deployment you would want to put nginx in front of it to serve static data.

If you just want do develop and test some things the server it comes with is absolutely enough and helps a lot with the debugging. Its as easy as typing "python myapp.py".


For deployment, it's also important to have something like nginx in front of Gunicorn to buffer requests from slow clients. Otherwise, this sort of thing can DoS your server pretty bad:

http://ha.ckers.org/slowloris/


I'll check out Gunicorn, thanks for the link.


Skip it and go with uWSGI ;) Emperor mode is fantastic.

Say you have /srv/mysite/uwsgi.ini and /srv/myothersite/uwsgi.ini (uwsgi config files for two different sites) you can run uwsgi --emperor /srv/*/uwsgi.ini and bam, it'll launch processes for all your sites.


I found myself similarly vexed when I first tried to deploy a Django project. Turns out I was making the process far more complicated by trying to wrestle with mod_wsgi and Apache.

I found that nginx + FastCGI[1] was by far the easiest configuration to get up and running. Took about 5 minutes to install the relevant packages and hack out a working configuration.

[1]http://wiki.nginx.org/HttpFastcgiModule


When you used php, your application server(mod_php) and web server(apache) looked the same to you. With python wsgi applications(most of the web frameworks are wsgi compliant), you generally need a separate application server and a web server which talks with the application server. Application server can directly serve the application and static files, but it isn't advisable.

So, you run an nginx on port 80 https://gist.github.com/rahulkmr/5232161 and proxy_pass to your application server running on some other port(8080 in the example).

You have a lot of choices when it comes to application servers. What you use depends on your use case.

> but I don't know how to configure nginx on my VPS so I can have multiple python webapps (my simple apps, django apps, flask etc.).

Look up sites-available and sites-enabled for nginx.


Have you considered using Heroku or Webfaction?

Apache + Django isn't too hard: the official docs cover it comprehensively: https://docs.djangoproject.com/en/1.5/howto/deployment/wsgi/...


Yes, I considered Webfraction. The thing is, I want to learn how to configure everyting by myself, because (1) I like learning and (2) I thnk it will be valuable lesson and let me understand better, how server work.

I'm more interested in nginx config, but I'll definetely read docs from the link you provided.


If the application in question is using WSGI to serve the content, I would e.g. advise to use nginx's built-in uwsgi protocol support (here 'uwsgi' denoting protocol and not the popular application server uWSGI itself) for performance reasons. I agree with sirn that uWSGI should not be easily overlooked. :)

uwsgi protocol is built-in in nginx >= 0.8.40; for older versions (and a general walkthrough), see http://uwsgi-docs.readthedocs.org/en/latest/Nginx.html

Here's the relevant bit for nginx's .conf:

  First of all copy the uwsgi_params file (available in the nginx directory of the uWSGI distribution [uWSGI here meaning the uWSGI application server, to be installed separately via your distro's package manager or e.g. pip]) into your Nginx configuration directory, then in a location directive in your Nginx configuration add:

    uwsgi_pass unix:///tmp/uwsgi.sock;
    include uwsgi_params;

  – or if you are using TCP sockets,

    uwsgi_pass 127.0.0.1:3031;
    include uwsgi_params;
(I would advise the former for performance reasons (unix sockets are faster))

  Then simply reload Nginx and you are ready to rock your uWSGI powered applications through Nginx.
Here are my nginx relevant directives - in server {} scope,

    set $server_root   /home/z/www/<basically,your_web_root>;
    set $uwsgi_socket  unix:$server_root/backend/var/uwsgi.sock;
Then (still in server {} scope),

    location /api { # my flask app serves <domain>.tld/api
      uwsgi_pass $uwsgi_socket;
      include uwsgi_params;
    }
That's it! That way I can reuse $uwsgi_socket as many times as is needed, etc.

The most simple way to launch the uWSGI app server would be to e.g.

  z@<hostname>:~/www/<web_root>/backend/lba$ cat test.sh

    #!/usr/bin/env bash
    uwsgi --post-buffering 1 --enable-threads -s /home/z/www/<web_root>/backend/var/uwsgi.sock -M -p 2 -w lba:app --chmod-socket 666 --pp ..

  uwsgi --help | grep "\-pp"
    --pp    add directory (or glob) to pythonpath
So we add a parent directory ("lba" containing the actual application files, e.g. __init__.py (can be empty) so that the directory could be imported (lba:app in uWSGI launch), etc.), tell uWSGI that this is to be the parent uwsgi process (-M), point it to its socket (-s), set number or processes (-p), tell it to actually load our 'WSGI module' (-w), and supply other per-application parameters which are not necessary if you just want to test things out.

app.py (lba:app) may simply contain (from http://flask.pocoo.org/docs/quickstart/) e.g.

  from flask import Flask
  app = Flask(__name__)

  @app.route('/')
  def hello_world():
    return 'Hello World!'

  if __name__ == '__main__':
    app.run()
That way you can test the sample app by simply sudo service nginx reload and ./test.sh (you might need sudo for the latter, too; also, might need to touch ../var/uwsgi.sock and look into uwsgi --help | grep "user") You can then put the test.sh (or the uwsgi call line itself) into e.g. supervisor - if the user privilege nuances are sorted out, you more or less have a production-worth setup (as far as nginx <-> uwsgi <-> your app is concerned), methinks.

edit sirn and antihero make a good point about Emperor mode


Actually, for anything that resembles production environment, I'd recommend using uWSGI in Emperor mode[1] to manage its instance than using Supervisor. Emperor mode will gracefully reload the app if config file's modification time changed (via `touch`) or stop and start the process automatically if you remove or add a configuration file.

My setup usually uses Upstart[2] (Ubuntu) or init script (Debian, etc.) to run uWSGI Emperor and make it scan /etc/uwsgi. When I need to deploy a new version, I just push the code then `touch /etc/uwsgi/myapp.ini` and my app is live with the code I just pushed.

[1] http://uwsgi-docs.readthedocs.org/en/latest/Emperor.html

[2] http://uwsgi-docs.readthedocs.org/en/latest/Upstart.html


I have nginx + gunicorn controlled by supervisord running and I must admit coming from LAMP it went not as smooth as I hoped.

For me the main problem was that all these parts have to be configured correctly or nothing much will happen at all. My advice is to first set up a static site in nginx, then try starting your project (using gunicorn) from the command line. Once your sure that both nginx and gunicorn work and know how to do it you can Google around for a supervisord + gunicorn tutorial for managing your apps.


> I have nginx + gunicorn controlled by supervisord running and I must admit coming from LAMP it went not as smooth as I hoped.

If you are so inclined, you can do it using Apache + mod_wsgi. That is very similar to how you do Apache + mod_php


mod_wsgi usage is not recommended.


Do you mean mod_wsgi or mod_python?


Sorry, got confused :) Was thinking mod_python.


According to whom?


I come from a PHP background too and in my opinion Python is far easier to use, whole stack. I wrote about it here http://blog.jmoz.co.uk/learning-python-the-pragmatic-way


All I can say is: keep at it. If you plan on using Django in the long term, you'll eventually get to the point where you know the steps and they don't seem that bad anymore.


a good thing would be to have ubuntu python ready servers as images , so you can just drop it on a vpn, config a few stuffs and get started.


I'd like to quickly plug Flask-Admin here, it's a much nicer experience than writing constant CRUD code for your administrative interface: https://github.com/MrJoes/Flask-Admin/

The author is quite friendly as well.


I'm between Flask and Pyramid for a new project, would love a hands-on comparison between the two.


So I've always wanted to start learnin some python and python web dev. I've only done webdev in node.js so far, and now I have the question : Django or Flask?


I've really enjoyed working with flask. Django is good, but it's a bit heavy for some projects


Start with Django, it has already made decisions for you.

Flask is much less opinionated, you will need to research more if you choose it.


Question: Is there a way to create application modules in the same style of Django modules (shippable extensions to an application) in Flask?

I've read about Flask blueprints, but that didn't seem to have the same angle... seemed to be more shippable libraries rather than a module of an application.


Blueprints are the same angle(better IMO). Develop the blueprint as a standalone module[1](templates, url rules, static files, before handlers...), and the mount it on the main application.

[1] Not python modules. I say module in the abstraction sense.

For eg, you can create a blueprint comments, define url rules('/', '/new', ':id/edit'...), add authentication to before handler(check before create, delete, edit), and then mount it on the main application.

app.register_blueprint(comments, url_prefix='/comments')

You can have blueprints which are self contained modules(comments), blueprints which just add jinja extensions, blueprints which bring in static assets etc etc. What does Django apps do which blueprints don't?



just a simple question: Why do we really need Flask, when we have Django?


Why do we need Python when we have PHP? Different people like different things. Would you prefer if the was only one library for every purpose?


I thought Flask was a minimal micro framework but this looks as bloated as Django.


> I thought Flask was a minimal micro framework but this looks as bloated as Django.

What kind of web applications have you written, and in what language/frameworks? My experience doesn't match yours. Flask is minimal in the sense that it doesn't add ORM, auth, assets etc to the core framework. There is nothing bloated about Flask, or even Django.


I think the fact that the tutorial shows off tons of plugins is a little confusing in this case. They aren't necessary at all and with them, it does look bloated.


Flask is anything but "minimal micro". It's a thin Sinatra-like facade over Werkzeug.


and it uses a lot more RAM compared to bottle.


That's to be expected. Flask builds on top of Werkzeug, itsdangerous and blinker whereas Bottle reimplements part of what Flask and the dependency libraries provides itself. However for the vast majority of applications having strong foundations to build upon is the right thing to do.


Flask is awesome, great job!


The difference between Flask's and Bottle's ram usage will be negligible. Out of box, flask is a wrapper over werkzeug and ships with Jinja2. The main memory usage will come from other libraries and extensions, and your own application code.


you've figured that out based on a simple hello world, right?




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: