Notes on Flask
Notes taken from the Flask documentation when the latest version was 0.9:
Foreword for experienced programmers
- Flask uses thread-local objects internally so that you don’t have to pass objects around from function to function within a request in order to stay threadsafe.
Quickstart
- The
Flaskconstructor takes the module or package name to know where to look for templates, static files, and so on. - If
debugis disabled, passhost='0.0.0.0'torun()to listen on all public IPs and make the server publicly available. - Setting
debugtoTrueallows the execution of arbitrary code, and so should never be run in production environments. - A variable part of an URL with a
pathconverter is like the default string converter, but also accepts slashes. - If a URL has a trailing slash, accessing it without one will automatically redirect; if a URL doesn’t have a trailing slash, accessing it with one will generate a 404.
- The
url_formethod maps keyword arguments to variable parts; unknown parts are appended as query parameters. - Method
PUTis similar toPOST, but the server might trigger the store procedure multiple times by overwriting the old values more than once. - Form data in a
PUTorPOSTrequest is accessed through theformattribute; query parameters are accessed throughargs. - Passing an error code to
abortcalls the corresponding method with anerrorhandler()decorator, which must return the error code after itsrender_template()call. - The
sessionobject is separate from therequestobject, and is implemented using cryptographically signed cookies. - To generate a good secret key for sessions, use the output from a call to
os.urandom(24).
Templates
- In templates you have access to the
config,request,session, andgobjects, and theurl_for()andget_flashed_messages()functions. - If using the
tojson()filter, chain it withsafe()if the output is displayed inside a<script>tag. - If you want to inject secure HTML into a template, wrap it in a
Markupobject before passing it to the template. - The keys and values returned by a context processor are merged with the template context, for all templates in the app.
Testing Flask applications
- Flask allows testing your application by exposing the Werkzeug test
Clientand handling the context locals for you. - The
TESTINGconfiguration flag disables the error catching during request handling so that you get better error reports when issuing requests. - Using
test_request_context()in awithstatement activates a request context temporarily, giving access to therequest,gandsessionobjects like in view functions. - The
before_request()andafter_request()functions aren’t called with a test request context; for the former, callpreprocess_request()yourself. - The
session_transaction()function allows creating or modifying a session before a request is issued in the context of the test client.
Logging application errors
- To override the human-readable time returned by
%(asctime)s, subclass the formatter and override theformatTime()method. - To configure loggers for third-party modules like
sqlalchemy, retrieve them usinggetLogger.
Configuration handling
- The
configattribute is where Flask itself puts certain configuration values, extensions put their configuration values, and you can put configuration values. - For debugging, set
TRAP_HTTP_EXCEPTIONStoTrueto not execute error handlers of HTTP exceptions, andTRAP_BAD_REQUEST_ERRORStoTrueto return tracebacks for Werkzeug andBadRequesterrors. - The
from_envvarfunction specifies an environment variable that is a pathname; its contents then override values in the configuration. - Best practice is to keep a default configuration, use an environment variable to switch between configurations, and use a tool like fabric to push code and configurations separately.
- Instance folders are suitable for values that change at runtime or configuration files, and can specify resources outside the application’s folder, or
Flask.root_path.
Signals
- The
connected_to()helper method allows temporarily subscribing a function to a signal with a context manager on its own. - Signals, or events, are singletons; to emit a signal, you must pass the sender to its
send()method. - If emitting a signal from a random function, you can pass
current_app._get_current_object()as the sender.
Pluggable views
- By representing views as methods of classes, you can use inheritance and pass differing arguments to the constructor to promote reuse and modularity.
- To specify decorators for the view function of a pluggable class, create a static, list variable named
decorators.
The application context
- The application context contains functionality that may be needed during a request, but is derived from the application, and not the request.
- The application context never moves between threads or is shared between requests, and is therefore suitable to store database connection information, etc.
The request context
- The request context is internally maintained as a stack; pushing and popping multiple times is useful to implement things like internal redirects.
- If a
before_request()function executed before the view returns a response, the other functions are no longer called. - With an unhandled exception, the
after_request()callbacks are not called, but theteardown_request()function is always executed. - Note that when using
with app.test_client()in tests,teardown_request()callbacks aren’t executed until the block has been exited. - Method
_get_current_object()returns the underlying proxied object for inheritance checks or when the real object reference is needed, like for sending signals.
Blueprints
- Blueprints provide separation at the Flask level, share application configuration, and can change an application object as necessary.
- Whether a blueprint can be mounted more than once depends on how it is implemented.
- A blueprint’s template folder is added to the searchpath of templates but with a lower priority than that of the application, allowing overriding of templates.
- When using
url_for()outside a blueprint, you must qualify endpoints with the blueprint name; inside the blueprint, prefix the endpoint with..
Patterns: Larger applications
- An
__init__.pyfile should create the Flask application object, and then import all the view functions.
Patterns: Deploying with Distribute
- distribute, formerly setuptools, extends distutils to add dependency support, a package registry, and
easy_install, soon to be replaced bypip. - Distributing resources with standard modules is not supported by distribute; your application must be a package.
- For distribute to lookup subpackages automatically instead of listing them explicitly, use
find_packages(). - To include the
templatesandstaticsubdirectories, add them to yourMANIFEST.infile and setinclude_package_datatoTrue. - The
installcommand copies into the site-packages folder;developcreates a symlink so changes are seen instantly.
Patterns: Deploying with Fabric
- To use Fabric, the application already has to be a package and requires a working
setup.pyfile. - All functions defined in
fabfile.pyare fab subcommands, and execute on hosts defined either in the file or on the command line. - The WSGI file must import the application and also set an environment variable so that the application knows where to find the configuration file.
- To handle differing configuration files between servers, copy them to all servers, and then symlink each file for a server to its expected location, like in
/var/www.
Patterns: SQLAlchemy in Flask
- If not using the Flask-SQLAlchemy extension, you must use
scoped_session, and have ateardown_requestdecorator that callsdb_session.remove().
Patterns: View decorators
- When defining a decorator, use
functools.wraps()to update the__name__,__module__, and some other attributes of a function. - Common decorator uses include redirecting logged out users to a login page when needed, and returning values from and populating a cache.
Patterns: Form validation with WTForms
- The Flask-WTF extension adds a handful of helper functions that make working with forms easier in Flask.
- Rendered fields in WTForms accept HTML attributes as keyword arguments, and because they are already HTML escaped, should be passed through the
|safefilter.
Patterns: Template inheritance
- The
extendstag must be the first tag in a child template. - To render the contents of a block defined in the parent template, use ``.
Patterns: Message flashing
- Flashing allows recording a message at the end of a request and accessing it on the next request, and only that request.
- Categories can be used to style messages differently, or to display only a subset of messages to the user.
Patterns: AJAX with jQuery
- The
url_for()method handles your application moving to a different path; in ascripttag, set the root asrequest.script_root|tojson|safe. - The
scripttag is declared CDATA and so there must not be</inside; thetojsonfilter will escape slashes for you in this context.
Patterns: Custom error pages
- If you have some kind of access control on your website, send a 403 (forbidden) code for disallowed resources.
- The 410 (gone) code is for resources that previously existed but were deleted.
Patterns: Deferred request callbacks
- If you must modify the response at a point where the response doesn’t exist yet, attach callbacks to the
gobject and call them in anafter_requestcallback.
API: Application object
- If using a single module, pass
__name__to theFlaskconstructor; if using a package, hardcode the name, or pass__name__.split('.')[0]. app_context()binds the application only; as long it is bound to the current context,flask.current_apppoints to that application.- When
debugisTrue, the debugger is run when an unhandled exception occurs, and the integrated server automatically recognizes changes to the code. - The
errorhandlerdecorator can be registered not just with status codes, but with arbitrary exception types. - By default the logger name is the name passed to the
Flaskconstructor. make_response()creates aresponse_classinstance; a passed string is used as the response body, or it accepts a(response, status, headers)tuple.- Instead of overriding
open_session, replace thesession_interface. permanent_session_lifetimespecifies the expiration date of a permanent session; by default it is 31 days.- To run the application in debug mode, but disable the code execution on the interactive debugger, pass
use_evalex=Falsetorun(). - Teardown functions registered with
teardown_request()must take every necessary step to avoid failure, like catching all exceptions. update_template_contextinjectsrequest,session,config, andg, and everything template context processors want to inject into the given template context.
API: Incoming request data
- The
valuesattribute combines the contents of bothformandargs. - If the mimetype is application/json then the JSON is stored in the
jsonattribute; otherwise it is in thedataattribute.
API: Response objects
- Typically you don’t have to create a response object because
make_response()will do this for you.
API: Sessions
- Modifications of mutable structures in a sessions are not picked up automatically; you must set
modifiedtoTrueyourself. - If
permanentisFalse, then the session will be deleted when the user closes the browser.
API: Session interface
- To aid user experience, a ready-only null session is used if real session support could not be loaded due to a configuration error.
API: Application globals
flask.gallows sharing data between functions for the lifetime of a request in a thread-safe manner; useful for storing the user currently logged in.
API: Useful functions and classes
- Function
make_response()delegates toflask.Flask.make_response(), and can accept the same parameters, like the status code. - The
after_this_requestdecorator is useful when not in a view function and the response object is not yet created. - Function
safe_join()safely joins a directory and filename, raisingNotFoundif the resulting path is outside the directory. - Wrapping a value in
Markupmarks it as without need for escaping; to actually escape a value before wrapping, callMarkup.escape(). Markupextends the unicode (string) class, and so it supports operations like%and+while escaping the arguments.
API: Returning JSON
- The
dumps()function of the JSON module is available as thetojsonfilter; inside a<script>tag, pass its output throughsafeto disable escaping.
API: Configuration
- When loading a configuration from a file or module, only uppercase keys are added, so lowercase values can be used as temporary ones.
- When loading configurations,
from_pyfile()behaves as if the file were imported withfrom_object(), andfrom_envvar()as if read usingfrom_pyfile().