Quickstart

Eager to get started? This page gives a good introduction to Flask. Itassumes you already have Flask installed. If you do not, head over to theInstallation section.

A Minimal Application

A minimal Flask application looks something like this:

  1. from flask import Flask
  2. app = Flask(__name__)
  3.  
  4. @app.route('/')
  5. def hello_world():
  6. return 'Hello, World!'

So what did that code do?

  • First we imported the Flask class. An instance of thisclass will be our WSGI application.

  • Next we create an instance of this class. The first argument is the name ofthe application’s module or package. If you are using a single module (asin this example), you should use name because depending on if it’sstarted as application or imported as module the name will be different('main' versus the actual import name). This is needed so thatFlask knows where to look for templates, static files, and so on. For moreinformation have a look at the Flask documentation.

  • We then use the route() decorator to tell Flask what URLshould trigger our function.

  • The function is given a name which is also used to generate URLs for thatparticular function, and returns the message we want to display in theuser’s browser.

Just save it as hello.py or something similar. Make sure to not callyour application flask.py because this would conflict with Flaskitself.

To run the application you can either use the flask command orpython’s -m switch with Flask. Before you can do that you needto tell your terminal the application to work with by exporting theFLASK_APP environment variable:

  1. $ export FLASK_APP=hello.py
  2. $ flask run
  3. * Running on http://127.0.0.1:5000/

If you are on Windows, the environment variable syntax depends on command lineinterpreter. On Command Prompt:

  1. C:\path\to\app>set FLASK_APP=hello.py

And on PowerShell:

  1. PS C:\path\to\app> $env:FLASK_APP = "hello.py"

Alternatively you can use python -m flask:

  1. $ export FLASK_APP=hello.py
  2. $ python -m flask run
  3. * Running on http://127.0.0.1:5000/

This launches a very simple builtin server, which is good enough for testingbut probably not what you want to use in production. For deployment options seeDeployment Options.

Now head over to http://127.0.0.1:5000/, and you should see your helloworld greeting.

Externally Visible Server

If you run the server you will notice that the server is only accessiblefrom your own computer, not from any other in the network. This is thedefault because in debugging mode a user of the application can executearbitrary Python code on your computer.

If you have the debugger disabled or trust the users on your network,you can make the server publicly available simply by adding—host=0.0.0.0 to the command line:

  1. $ flask run --host=0.0.0.0

This tells your operating system to listen on all public IPs.

What to do if the Server does not Start

In case the python -m flask fails or flaskdoes not exist, there are multiple reasons this might be the case.First of all you need to look at the error message.

Old Version of Flask

Versions of Flask older than 0.11 use to have different ways to start theapplication. In short, the flask command did not exist, andneither did python -m flask. In that case you have two options:either upgrade to newer Flask versions or have a look at the Development Serverdocs to see the alternative method for running a server.

Invalid Import Name

The FLASK_APP environment variable is the name of the module to import atflask run. In case that module is incorrectly named you will get animport error upon start (or if debug is enabled when you navigate to theapplication). It will tell you what it tried to import and why it failed.

The most common reason is a typo or because you did not actually create anapp object.

Debug Mode

(Want to just log errors and stack traces? See Application Errors)

The flask script is nice to start a local development server, butyou would have to restart it manually after each change to your code.That is not very nice and Flask can do better. If you enable debugsupport the server will reload itself on code changes, and it will alsoprovide you with a helpful debugger if things go wrong.

To enable all development features (including debug mode) you can exportthe FLASK_ENV environment variable and set it to developmentbefore running the server:

  1. $ export FLASK_ENV=development
  2. $ flask run

(On Windows you need to use set instead of export.)

This does the following things:

  • it activates the debugger

  • it activates the automatic reloader

  • it enables the debug mode on the Flask application.

You can also control debug mode separately from the environment byexporting FLASK_DEBUG=1.

There are more parameters that are explained in the Development Server docs.

Attention

Even though the interactive debugger does not work in forking environments(which makes it nearly impossible to use on production servers), it stillallows the execution of arbitrary code. This makes it a major security riskand therefore it must never be used on production machines.

Screenshot of the debugger in action:screenshot of debugger in actionMore information on using the debugger can be found in the Werkzeugdocumentation.

Have another debugger in mind? See Working with Debuggers.

Routing

Modern web applications use meaningful URLs to help users. Users are morelikely to like a page and come back if the page uses a meaningful URL they canremember and use to directly visit a page.

Use the route() decorator to bind a function to a URL.

  1. @app.route('/')def index(): return 'Index Page'

  2. @app.route('/hello')def hello(): return 'Hello, World'

You can do more! You can make parts of the URL dynamic and attach multiplerules to a function.

Variable Rules

You can add variable sections to a URL by marking sections with<variable_name>. Your function then receives the <variable_name>as a keyword argument. Optionally, you can use a converter to specify the typeof the argument like <converter:variable_name>.

  1. @app.route('/user/<username>')def show_user_profile(username):

  2. # show the user profile for that user
  3. return &#39;User %s&#39; % escape(username)
  4. @app.route('/post/<int:post_id>')def show_post(post_id):

  5. # show the post with the given id, the id is an integer
  6. return &#39;Post %d&#39; % post_id
  7. @app.route('/path/<path:subpath>')def show_subpath(subpath):

  8. # show the subpath after /path/
  9. return &#39;Subpath %s&#39; % escape(subpath)

Converter types:

string(default) accepts any text without a slash
intaccepts positive integers
floataccepts positive floating point values
pathlike string but also accepts slashes
uuidaccepts UUID strings

Unique URLs / Redirection Behavior

The following two rules differ in their use of a trailing slash.

  1. @app.route('/projects/')def projects(): return 'The project page'

  2. @app.route('/about')def about(): return 'The about page'

The canonical URL for the projects endpoint has a trailing slash.It’s similar to a folder in a file system. If you access the URL withouta trailing slash, Flask redirects you to the canonical URL with thetrailing slash.

The canonical URL for the about endpoint does not have a trailingslash. It’s similar to the pathname of a file. Accessing the URL with atrailing slash produces a 404 “Not Found” error. This helps keep URLsunique for these resources, which helps search engines avoid indexingthe same page twice.

URL Building

To build a URL to a specific function, use the url_for() function.It accepts the name of the function as its first argument and any number ofkeyword arguments, each corresponding to a variable part of the URL rule.Unknown variable parts are appended to the URL as query parameters.

Why would you want to build URLs using the URL reversing functionurl_for() instead of hard-coding them into your templates?

  • Reversing is often more descriptive than hard-coding the URLs.

  • You can change your URLs in one go instead of needing to remember tomanually change hard-coded URLs.

  • URL building handles escaping of special characters and Unicode datatransparently.

  • The generated paths are always absolute, avoiding unexpected behaviorof relative paths in browsers.

  • If your application is placed outside the URL root, for example, in/myapplication instead of /, url_for() properlyhandles that for you.

For example, here we use the test_request_context() methodto try out url_for(). test_request_context()tells Flask to behave as though it’s handling a request even while we use aPython shell. See Context Locals.

  1. from flask import Flask, escape, url_for
  2.  
  3. app = Flask(__name__)
  4.  
  5. @app.route('/')
  6. def index():
  7. return 'index'
  8.  
  9. @app.route('/login')
  10. def login():
  11. return 'login'
  12.  
  13. @app.route('/user/<username>')
  14. def profile(username):
  15. return '{}\'s profile'.format(escape(username))
  16.  
  17. with app.test_request_context():
  18. print(url_for('index'))
  19. print(url_for('login'))
  20. print(url_for('login', next='/'))
  21. print(url_for('profile', username='John Doe'))
  1. /
  2. /login
  3. /login?next=/
  4. /user/John%20Doe

HTTP Methods

Web applications use different HTTP methods when accessing URLs. You shouldfamiliarize yourself with the HTTP methods as you work with Flask. By default,a route only answers to GET requests. You can use the methods argumentof the route() decorator to handle different HTTP methods.

  1. from flask import request
  2.  
  3. @app.route('/login', methods=['GET', 'POST'])
  4. def login():
  5. if request.method == 'POST':
  6. return do_the_login()
  7. else:
  8. return show_the_login_form()

If GET is present, Flask automatically adds support for the HEAD methodand handles HEAD requests according to the HTTP RFC. Likewise,OPTIONS is automatically implemented for you.

Static Files

Dynamic web applications also need static files. That’s usually wherethe CSS and JavaScript files are coming from. Ideally your web server isconfigured to serve them for you, but during development Flask can do thatas well. Just create a folder called static in your package or next toyour module and it will be available at /static on the application.

To generate URLs for static files, use the special 'static' endpoint name:

  1. url_for('static', filename='style.css')

The file has to be stored on the filesystem as static/style.css.

Rendering Templates

Generating HTML from within Python is not fun, and actually prettycumbersome because you have to do the HTML escaping on your own to keepthe application secure. Because of that Flask configures the Jinja2 template engine for you automatically.

To render a template you can use the render_template()method. All you have to do is provide the name of the template and thevariables you want to pass to the template engine as keyword arguments.Here’s a simple example of how to render a template:

  1. from flask import render_template
  2.  
  3. @app.route('/hello/')
  4. @app.route('/hello/<name>')
  5. def hello(name=None):
  6. return render_template('hello.html', name=name)

Flask will look for templates in the templates folder. So if yourapplication is a module, this folder is next to that module, if it’s apackage it’s actually inside your package:

Case 1: a module:

  1. /application.py
  2. /templates
  3. /hello.html

Case 2: a package:

  1. /application
  2. /__init__.py
  3. /templates
  4. /hello.html

For templates you can use the full power of Jinja2 templates. Head overto the official Jinja2 Template Documentation for more information.

Here is an example template:

  1. <!doctype html>
  2. <title>Hello from Flask</title>
  3. {% if name %}
  4. <h1>Hello {{ name }}!</h1>
  5. {% else %}
  6. <h1>Hello, World!</h1>
  7. {% endif %}

Inside templates you also have access to the request,session and g1 objectsas well as the get_flashed_messages() function.

Templates are especially useful if inheritance is used. If you want toknow how that works, head over to the Template Inheritance patterndocumentation. Basically template inheritance makes it possible to keepcertain elements on each page (like header, navigation and footer).

Automatic escaping is enabled, so if name contains HTML it will be escapedautomatically. If you can trust a variable and you know that it will besafe HTML (for example because it came from a module that converts wikimarkup to HTML) you can mark it as safe by using theMarkup class or by using the |safe filter in thetemplate. Head over to the Jinja 2 documentation for more examples.

Here is a basic introduction to how the Markup class works:

  1. >>> from flask import Markup
  2. >>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
  3. Markup(u'<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')
  4. >>> Markup.escape('<blink>hacker</blink>')
  5. Markup(u'&lt;blink&gt;hacker&lt;/blink&gt;')
  6. >>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
  7. u'Marked up \xbb HTML'

Changelog

Changed in version 0.5: Autoescaping is no longer enabled for all templates. The followingextensions for templates trigger autoescaping: .html, .htm,.xml, .xhtml. Templates loaded from a string will haveautoescaping disabled.

  • 1
  • Unsure what that g object is? It’s something in whichyou can store information for your own needs, check the documentation ofthat object (g) and the Using SQLite 3 with Flask for moreinformation.

Accessing Request Data

For web applications it’s crucial to react to the data a client sends tothe server. In Flask this information is provided by the globalrequest object. If you have some experience with Pythonyou might be wondering how that object can be global and how Flaskmanages to still be threadsafe. The answer is context locals:

Context Locals

Insider Information

If you want to understand how that works and how you can implementtests with context locals, read this section, otherwise just skip it.

Certain objects in Flask are global objects, but not of the usual kind.These objects are actually proxies to objects that are local to a specificcontext. What a mouthful. But that is actually quite easy to understand.

Imagine the context being the handling thread. A request comes in and theweb server decides to spawn a new thread (or something else, theunderlying object is capable of dealing with concurrency systems otherthan threads). When Flask starts its internal request handling itfigures out that the current thread is the active context and binds thecurrent application and the WSGI environments to that context (thread).It does that in an intelligent way so that one application can invoke anotherapplication without breaking.

So what does this mean to you? Basically you can completely ignore thatthis is the case unless you are doing something like unit testing. Youwill notice that code which depends on a request object will suddenly breakbecause there is no request object. The solution is creating a requestobject yourself and binding it to the context. The easiest solution forunit testing is to use the test_request_context()context manager. In combination with the with statement it will bind atest request so that you can interact with it. Here is an example:

  1. from flask import request
  2.  
  3. with app.test_request_context('/hello', method='POST'):
  4. # now you can do something with the request until the
  5. # end of the with block, such as basic assertions:
  6. assert request.path == '/hello'
  7. assert request.method == 'POST'

The other possibility is passing a whole WSGI environment to therequest_context() method:

  1. from flask import request
  2.  
  3. with app.request_context(environ):
  4. assert request.method == 'POST'

The Request Object

The request object is documented in the API section and we will not coverit here in detail (see Request). Here is a broad overview ofsome of the most common operations. First of all you have to import it fromthe flask module:

  1. from flask import request

The current request method is available by using themethod attribute. To access form data (datatransmitted in a POST or PUT request) you can use theform attribute. Here is a full example of the twoattributes mentioned above:

  1. @app.route('/login', methods=['POST', 'GET'])def login(): error = None if request.method == 'POST': if valid_login(request.form['username'], request.form['password']): return log_the_user_in(request.form['username']) else: error = 'Invalid username/password'

  2. # the code below is executed if the request method
  3. # was GET or the credentials were invalid
  4. return render_template(&#39;login.html&#39;, error=error)

What happens if the key does not exist in the form attribute? In thatcase a special KeyError is raised. You can catch it like astandard KeyError but if you don’t do that, a HTTP 400 Bad Requesterror page is shown instead. So for many situations you don’t have todeal with that problem.

To access parameters submitted in the URL (?key=value) you can use theargs attribute:

  1. searchword = request.args.get('key', '')

We recommend accessing URL parameters with get or by catching theKeyError because users might change the URL and presenting them a 400bad request page in that case is not user friendly.

For a full list of methods and attributes of the request object, head overto the Request documentation.

File Uploads

You can handle uploaded files with Flask easily. Just make sure not toforget to set the enctype="multipart/form-data" attribute on your HTMLform, otherwise the browser will not transmit your files at all.

Uploaded files are stored in memory or at a temporary location on thefilesystem. You can access those files by looking at thefiles attribute on the request object. Eachuploaded file is stored in that dictionary. It behaves just like astandard Python file object, but it also has asave() method thatallows you to store that file on the filesystem of the server.Here is a simple example showing how that works:

  1. from flask import request
  2.  
  3. @app.route('/upload', methods=['GET', 'POST'])
  4. def upload_file():
  5. if request.method == 'POST':
  6. f = request.files['the_file']
  7. f.save('/var/www/uploads/uploaded_file.txt')
  8. ...

If you want to know how the file was named on the client before it wasuploaded to your application, you can access thefilename attribute.However please keep in mind that this value can be forgedso never ever trust that value. If you want to use the filenameof the client to store the file on the server, pass it through thesecure_filename() function thatWerkzeug provides for you:

  1. from flask import request
  2. from werkzeug.utils import secure_filename
  3.  
  4. @app.route('/upload', methods=['GET', 'POST'])
  5. def upload_file():
  6. if request.method == 'POST':
  7. f = request.files['the_file']
  8. f.save('/var/www/uploads/' + secure_filename(f.filename))
  9. ...

For some better examples, checkout the Uploading Files pattern.

Cookies

To access cookies you can use the cookiesattribute. To set cookies you can use theset_cookie method of response objects. Thecookies attribute of request objects is adictionary with all the cookies the client transmits. If you want to usesessions, do not use the cookies directly but instead use theSessions in Flask that add some security on top of cookies for you.

Reading cookies:

  1. from flask import request
  2.  
  3. @app.route('/')
  4. def index():
  5. username = request.cookies.get('username')
  6. # use cookies.get(key) instead of cookies[key] to not get a
  7. # KeyError if the cookie is missing.

Storing cookies:

  1. from flask import make_response
  2.  
  3. @app.route('/')
  4. def index():
  5. resp = make_response(render_template(...))
  6. resp.set_cookie('username', 'the username')
  7. return resp

Note that cookies are set on response objects. Since you normallyjust return strings from the view functions Flask will convert them intoresponse objects for you. If you explicitly want to do that you can usethe make_response() function and then modify it.

Sometimes you might want to set a cookie at a point where the responseobject does not exist yet. This is possible by utilizing theDeferred Request Callbacks pattern.

For this also see About Responses.

Redirects and Errors

To redirect a user to another endpoint, use the redirect()function; to abort a request early with an error code, use theabort() function:

  1. from flask import abort, redirect, url_for
  2.  
  3. @app.route('/')
  4. def index():
  5. return redirect(url_for('login'))
  6.  
  7. @app.route('/login')
  8. def login():
  9. abort(401)
  10. this_is_never_executed()

This is a rather pointless example because a user will be redirected fromthe index to a page they cannot access (401 means access denied) but itshows how that works.

By default a black and white error page is shown for each error code. Ifyou want to customize the error page, you can use theerrorhandler() decorator:

  1. from flask import render_template
  2.  
  3. @app.errorhandler(404)
  4. def page_not_found(error):
  5. return render_template('page_not_found.html'), 404

Note the 404 after the render_template() call. Thistells Flask that the status code of that page should be 404 which meansnot found. By default 200 is assumed which translates to: all went well.

See Error handlers for more details.

About Responses

The return value from a view function is automatically converted intoa response object for you. If the return value is a string it’sconverted into a response object with the string as response body, a200 OK status code and a text/html mimetype. If thereturn value is a dict, jsonify() is called to produce a response.The logic that Flask applies to converting return values into responseobjects is as follows:

  • If a response object of the correct type is returned it’s directlyreturned from the view.

  • If it’s a string, a response object is created with that data andthe default parameters.

  • If it’s a dict, a response object is created using jsonify.

  • If a tuple is returned the items in the tuple can provide extrainformation. Such tuples have to be in the form(response, status), (response, headers), or(response, status, headers). The status value will overridethe status code and headers can be a list or dictionary ofadditional header values.

  • If none of that works, Flask will assume the return value is avalid WSGI application and convert that into a response object.

If you want to get hold of the resulting response object inside the viewyou can use the make_response() function.

Imagine you have a view like this:

  1. @app.errorhandler(404)def not_found(error): return render_template('error.html'), 404

You just need to wrap the return expression withmake_response() and get the response object to modify it, thenreturn it:

  1. @app.errorhandler(404)def not_found(error): resp = make_response(render_template('error.html'), 404) resp.headers['X-Something'] = 'A value' return resp

APIs with JSON

A common response format when writing an API is JSON. It’s easy to getstarted writing such an API with Flask. If you return a dict from aview, it will be converted to a JSON response.

  1. @app.route("/me")def me_api(): user = get_current_user() return { "username": user.username, "theme": user.theme, "image": url_for("user_image", filename=user.image), }

Depending on your API design, you may want to create JSON responses fortypes other than dict. In that case, use thejsonify() function, which will serialize any supportedJSON data type. Or look into Flask community extensions that supportmore complex applications.

  1. @app.route("/users")def users_api(): users = get_all_users() return jsonify([user.to_json() for user in users])

Sessions

In addition to the request object there is also a second object calledsession which allows you to store information specific to auser from one request to the next. This is implemented on top of cookiesfor you and signs the cookies cryptographically. What this means is thatthe user could look at the contents of your cookie but not modify it,unless they know the secret key used for signing.

In order to use sessions you have to set a secret key. Here is howsessions work:

  1. from flask import Flask, session, redirect, url_for, escape, request
  2.  
  3. app = Flask(__name__)
  4.  
  5. # Set the secret key to some random bytes. Keep this really secret!
  6. app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
  7.  
  8. @app.route('/')
  9. def index():
  10. if 'username' in session:
  11. return 'Logged in as %s' % escape(session['username'])
  12. return 'You are not logged in'
  13.  
  14. @app.route('/login', methods=['GET', 'POST'])
  15. def login():
  16. if request.method == 'POST':
  17. session['username'] = request.form['username']
  18. return redirect(url_for('index'))
  19. return '''
  20. <form method="post">
  21. <p><input type=text name=username>
  22. <p><input type=submit value=Login>
  23. </form>
  24. '''
  25.  
  26. @app.route('/logout')
  27. def logout():
  28. # remove the username from the session if it's there
  29. session.pop('username', None)
  30. return redirect(url_for('index'))

The escape() mentioned here does escaping for you if you arenot using the template engine (as in this example).

How to generate good secret keys

A secret key should be as random as possible. Your operating system hasways to generate pretty random data based on a cryptographic randomgenerator. Use the following command to quickly generate a value forFlask.secret_key (or SECRET_KEY):

  1. $ python -c 'import os; print(os.urandom(16))'
  2. b'_5#y2L"F4Q8z\n\xec]/'

A note on cookie-based sessions: Flask will take the values you put into thesession object and serialize them into a cookie. If you are finding somevalues do not persist across requests, cookies are indeed enabled, and you arenot getting a clear error message, check the size of the cookie in your pageresponses compared to the size supported by web browsers.

Besides the default client-side based sessions, if you want to handlesessions on the server-side instead, there are severalFlask extensions that support this.

Message Flashing

Good applications and user interfaces are all about feedback. If the userdoes not get enough feedback they will probably end up hating theapplication. Flask provides a really simple way to give feedback to auser with the flashing system. The flashing system basically makes itpossible to record a message at the end of a request and access it on the next(and only the next) request. This is usually combined with a layouttemplate to expose the message.

To flash a message use the flash() method, to get hold of themessages you can use get_flashed_messages() which is alsoavailable in the templates. Check out the Message Flashingfor a full example.

Logging

Changelog

New in version 0.3.

Sometimes you might be in a situation where you deal with data thatshould be correct, but actually is not. For example you may havesome client-side code that sends an HTTP request to the serverbut it’s obviously malformed. This might be caused by a user tamperingwith the data, or the client code failing. Most of the time it’s okayto reply with 400 Bad Request in that situation, but sometimesthat won’t do and the code has to continue working.

You may still want to log that something fishy happened. This is whereloggers come in handy. As of Flask 0.3 a logger is preconfigured for youto use.

Here are some example log calls:

  1. app.logger.debug('A value for debugging')
  2. app.logger.warning('A warning occurred (%d apples)', 42)
  3. app.logger.error('An error occurred')

The attached logger is a standard loggingLogger, so head over to the official loggingdocs for more information.

Read more on Application Errors.

Hooking in WSGI Middlewares

If you want to add a WSGI middleware to your application you can wrap theinternal WSGI application. For example if you want to use one of themiddlewares from the Werkzeug package to work around bugs in lighttpd, youcan do it like this:

  1. from werkzeug.contrib.fixers import LighttpdCGIRootFix
  2. app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)

Using Flask Extensions

Extensions are packages that help you accomplish common tasks. Forexample, Flask-SQLAlchemy provides SQLAlchemy support that makes it simpleand easy to use with Flask.

For more on Flask extensions, have a look at Extensions.

Deploying to a Web Server

Ready to deploy your new Flask app? Go to Deployment Options.