Advanced Flask Patterns
speakerdeck.com
speakerdeck.com
I have no doubt that if I dug into it then it would all make sense, but my first instinct is this: how much of this complexity (proxy objects to thread locals, context stacks etc) results from the fact that doing:
from flask import request
is just a bad idea?Perhaps things would be easier if instead of:
from flask import request
...
@app.route('/'):
def index():
return "Hello from %s" % request.args.get('name')
we did: @app.route('/'):
def index(request):
return "Hello from %s" % request.args.get('name')
I'm probably massively over-simplifying things, but the idea of magically importing state is the one aspect of Flask that always felt a bit odd to me. Yes it is usually not such a bright idea to use thread locals. They cause
troubles for servers that are not based on the concept of threads and make
large applications harder to maintain. However Flask is just not designed
for large applications or asynchronous servers. Flask wants to make it quick
and easy to write a traditional web application.
http://flask.pocoo.org/docs/design/#thread-localsIf you have a large application, should you use what, Spring? If you use Spring, you'll have a large application.
What would Python developers prefer to use for a large application - Django?
Server-side web application frameworks are a well-understood and rigid domain: there is only so much variation you can get in the core structure, so it's easy to keep in mind the meaning and scope of Flask's "magic" implicit state variables.
I have used (and continue using) Flask for small- and medium-size projects, and thread-locals so far haven't been a maintenance burden.
The fact that you can do `_app_ctx_stack.top.mydatabase_connection` to get a database connection from anywhere is very helpful. Frameworks that did not expose thread locals still have them. Just special cased for certain things.
How does User.objects.all() get to the current transaction? Correct: a thread local. It's just hidden in the core of the framework. Not having a thread local there is nearly impossible, especially if you need to work with foreign libraries that do not support passing in of information. It's just going to cause a horrible API. (Not for the view case, but for things like database connections)
Flask does not hide things from you. It is very explicit, honest and upfront with everything it's doing. Is it the best solution? I am pretty sure it's not. I do however think that it's a very viable one.
The talk is very advanced and I think I did not make that clear enough from the summary on the website and I learned from that. I also plan on doing a “postmortem” that gives more context into some of the things the talk was mentioning and why it works the way it works.
TL;DR: you can't live without thread locals or you have a horrible API. Flask embraces them on every level and tells you how you can deal with the downsides of it.
flask seems to make good use of these. For GUI client programming, FLTK does the same thing marvelously - FLTK code is often 3-4 times shorter and simpler than any other GUI API/framework I've used, and it usually performs much better as well.
In general, the "missing piece" that makes globals/TLS at-least-as-usable-as-pass-everything-explicitly, is "push state"/"pop state", which allows you to do reentrant calls -- usually works much, much better than passing the state as an argument everywhere.
edit: I originally wrote "but flask probably doesn't need a state stack", but then I got to the slide that says it does have them :) silly me, apologies.
Would definitely recommend… I was at the talk yesterday, very clever stuff.
Anyone care to explain what these advanced patterns are useful for?
That would make it a lot easier to maintain thread state, e.g. an open database connection, without having to use a singleton.
It's not intended to be used by newcomers. It's for people that write Flask extensions that should work in a wide range of environments. The word “advanced” is in there for a good reason.