CoolFace
Datasetpublic

enigmare/v2-crawler

sourceHugging Faceupdated 28d agoView on Hugging Face
1likes904downloads
flask_palletsprojects_com.jsonl74 linesDownload Raw Back to documentation
1{"id":"doc-async_with_gevent_flask_documentation_3_1_x-56d4ef27","source":"documentation","title":"Async with Gevent — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/gevent/","text":"Async with Gevent¶ Gevent patches Python’s standard library to run within special async workers called greenlets. Gevent has existed since long before Python’s native asyncio was available, and Flask has always worked with it. Gevent is a reliable way to handle numerous, long lived, concurrent connections, and to achieve similar capabilities to ASGI and asyncio. This works without needing to write async def or await anywhere, but relies on gevent and greenlet’s low level manipulation of the Python interpreter. Deciding whether you should use gevent with Flask, or Quart, or something else, is ultimately up to understanding the specific needs of your project. Enabling gevent¶ You need to apply gevent’s patching as early as possible in your code. This enables gevent’s underlying event loop and converts many Python internals to run inside it. Add the following at the top of your project’s module or top __init__.py: import gevent.monkey gevent.monkey.patch_all() When deploying in production, use Gunicorn or uWSGI with a gevent worker, as described on those pages. To run concurrent tasks within your own code, such as views, use gevent.spawn(): @app.post(\"/send\") def send_email(): gevent.spawn(email.send, to=\"example@example.example\", text=\"example\") return \"Email is being sent.\" If you need to access request or other Flask context globals within the spawned function, decorate the function with stream_with_context() or copy_current_request_context(). Prefer passing the exact data you need when spawning the function, rather than using the decorators. Note When using gevent, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is required. Combining with async/await¶ Gevent’s patching does not interact well with Flask’s built-in asyncio support. If you want to use Gevent and asyncio in the same app, you’ll need to override flask.Flask.async_to_sync() to run async functions inside gevent. import gevent.monkey gevent.monkey.patch_all() import asyncio from flask import Flask, request loop = asyncio.EventLoop() gevent.spawn(loop.run_forever) class GeventFlask(Flask): def async_to_sync(self, func): def run(*args, **kwargs): coro = func(*args, **kwargs) future = asyncio.run_coroutine_threadsafe(coro, loop) return future.result() return run app = GeventFlask(__name__) @app.get(\"/\") async def greet(): await asyncio.sleep(1) return f\"Hello, {request.args.get(\"name\", \"World\")}!\" This starts an asyncio event loop in a gevent worker. Async functions are scheduled on that event loop. This may still have limitations, and may need to be modified further when using other asyncio implementations. libuv¶ libuv is another event loop implementation that gevent supports. There’s also a project called uvloop that enables libuv in asyncio. If you want to use libuv, use gevent’s support, not uvloop. It may be possible to further modify the async_to_sync code from the previous section to work with uvloop, but that’s not currently known. To enable gevent’s libuv support, add the following at the very top of your code, before gevent.monkey.patch_all(): import gevent gevent.config.loop = \"libuv\" import gevent.monkey gevent.monkey.patch_all() Contents Async with Gevent Enabling gevent Combining with async/await libuv Navigation Overview httpd async and await Quick search\n\nExample:\n```text\nimport gevent.monkey\ngevent.monkey.patch_all()\n```\n\nExample:\n```text\n@app.post(\"/send\")\ndef send_email():\n    gevent.spawn(email.send, to=\"example@example.example\", text=\"example\")\n    return \"Email is being sent.\"\n```\n\nExample:\n```text\nimport gevent.monkey\ngevent.monkey.patch_all()\n\nimport asyncio\nfrom flask import Flask, request\n\nloop = asyncio.EventLoop()\ngevent.spawn(loop.run_forever)\n\nclass GeventFlask(Flask):\n    def async_to_sync(self, func):\n        def run(*args, **kwargs):\n            coro = func(*args, **kwargs)\n            future = asyncio.run_coroutine_threadsafe(coro, loop)\n            return future.result()\n\n        return run\n\napp = GeventFlask(__name__)\n\n@app.get(\"/\")\nasync def greet():\n    await asyncio.sleep(1)\n    return f\"Hello, {request.args.get(\"name\", \"World\")}!\"\n```\n\nExample:\n```text\nimport gevent\ngevent.config.loop = \"libuv\"\n\nimport gevent.monkey\ngevent.monkey.patch_all()\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.728Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":54,"estimatedTokens":1061}}2{"id":"doc-request_content_checksums_flask_documentation_3_-fea4ea1b","source":"documentation","title":"Request Content Checksums — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/requestchecksum/","text":"Request Content Checksums¶ Various pieces of code can consume the request data and preprocess it. For instance JSON data ends up on the request object already read and processed, form data ends up there as well but goes through a different code path. This seems inconvenient when you want to calculate the checksum of the incoming request data. This is necessary sometimes for some APIs. Fortunately this is however very simple to change by wrapping the input stream. The following example calculates the SHA1 checksum of the incoming data as it gets read and stores it in the WSGI hashlib class ChecksumCalcStream(object): def __init__(self, stream): self._stream = stream self._hash = hashlib.sha1() def read(self, bytes): rv = self._stream.read(bytes) self._hash.update(rv) return rv def readline(self, size_hint): rv = self._stream.readline(size_hint) self._hash.update(rv) return rv def generate_checksum(request): env = request.environ stream = ChecksumCalcStream(env['wsgi.input']) env['wsgi.input'] = stream return stream._hash To use this, all you need to do is to hook the calculating stream in before the request starts consuming data. (Eg: be careful accessing request.form or anything of that nature. before_request_handlers for instance should be careful not to access it). Example usage: @app.route('/special-api', methods=['POST']) def special_api(): hash = generate_checksum(request) # Accessing this parses the input stream files = request.files # At this point the hash is fully constructed. checksum = hash.hexdigest() return f\"Hash was: {checksum}\" Navigation Overview Patterns for Flask HTTP Method Overrides Tasks with Celery Quick search\n\nExample:\n```text\nimport hashlib\n\nclass ChecksumCalcStream(object):\n\n    def __init__(self, stream):\n        self._stream = stream\n        self._hash = hashlib.sha1()\n\n    def read(self, bytes):\n        rv = self._stream.read(bytes)\n        self._hash.update(rv)\n        return rv\n\n    def readline(self, size_hint):\n        rv = self._stream.readline(size_hint)\n        self._hash.update(rv)\n        return rv\n\ndef generate_checksum(request):\n    env = request.environ\n    stream = ChecksumCalcStream(env['wsgi.input'])\n    env['wsgi.input'] = stream\n    return stream._hash\n```\n\nExample:\n```text\n@app.route('/special-api', methods=['POST'])\ndef special_api():\n    hash = generate_checksum(request)\n    # Accessing this parses the input stream\n    files = request.files\n    # At this point the hash is fully constructed.\n    checksum = hash.hexdigest()\n    return f\"Hash was: {checksum}\"\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.728Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":42,"estimatedTokens":642}}3{"id":"doc-security_considerations_flask_documentation_3_1_-6636405e","source":"documentation","title":"Security Considerations — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/web-security/","text":"Security Considerations¶ Web applications face many types of potential security problems, and it can be hard to get everything right, or even to know what “right” is in general. Flask tries to solve a few of these things by default, but there are other parts you may have to take care of yourself. Many of these solutions are tradeoffs, and will depend on each application’s specific needs and threat model. Many hosting platforms may take care of certain types of problems without the need for the Flask application to handle them. Resource Use¶ A common category of attacks is “Denial of Service” (DoS or DDoS). This is a very broad category, and different variants target different layers in a deployed application. In general, something is done to increase how much processing time or memory is used to handle each request, to the point where there are not enough resources to handle legitimate requests. Flask provides a few configuration options to handle resource use. They can also be set on individual requests to customize only that request. The documentation for each goes into more detail. MAX_CONTENT_LENGTH or Request.max_content_length controls how much data will be read from a request. It is not set by default, although it will still block truly unlimited streams unless the WSGI server indicates support. MAX_FORM_MEMORY_SIZE or Request.max_form_memory_size controls how large any non-file multipart/form-data field can be. It is set to 500kB by default. MAX_FORM_PARTS or Request.max_form_parts controls how many multipart/form-data fields can be parsed. It is set to 1000 by default. Combined with the default max_form_memory_size, this means that a form will occupy at most 500MB of memory. Regardless of these settings, you should also review what settings are available from your operating system, container deployment (Docker etc), WSGI server, HTTP server, and hosting platform. They typically have ways to set process resource limits, timeouts, and other checks regardless of how Flask is configured. Cross-Site Scripting (XSS)¶ Cross site scripting is the concept of injecting arbitrary HTML (and with it JavaScript) into the context of a website. To remedy this, developers have to properly escape text so that it cannot include arbitrary HTML tags. For more information on that have a look at the Wikipedia article on Cross-Site Scripting. Flask configures Jinja to automatically escape all values unless explicitly told otherwise. This should rule out all XSS problems caused in templates, but there are still other places where you have to be HTML without the help of Jinja calling Markup on data submitted by users sending out HTML from uploaded files, never do that, use the header to prevent that problem. sending out textfiles from uploaded files. Some browsers are using content-type guessing based on the first few bytes so users could trick a browser to execute HTML. Another thing that is very important are unquoted attributes. While Jinja can protect you from XSS issues by escaping HTML, there is one thing it cannot protect you by attribute injection. To counter this possible attack vector, be sure to always quote your attributes with either double or single quotes when using Jinja expressions in them: <input value=\"{{ value }}\"> Why is this necessary? Because if you would not be doing that, an attacker could easily inject custom JavaScript handlers. For example an attacker could inject this piece of HTML+JavaScript: onmouseover=alert(document.cookie) When the user would then move with the mouse over the input, the cookie would be presented to the user in an alert window. But instead of showing the cookie to the user, a good attacker might also execute any other JavaScript code. In combination with CSS injections the attacker might even make the element fill out the entire page so that the user would just have to have the mouse anywhere on the page to trigger the attack. There is one class of XSS issues that Jinja’s escaping does not protect against. The a tag’s href attribute can contain a , which the browser will execute when clicked if not secured properly. <a href=\"{{ value }}\">click here</a> <a href=\"javascript:alert('unsafe');\">click here</a> To prevent this, you’ll need to set the Content Security Policy (CSP) response header. Cross-Site Request Forgery (CSRF)¶ Another big problem is CSRF. This is a very complex topic and I won’t outline it here in detail just mention what it is and how to theoretically prevent it. If your authentication information is stored in cookies, you have implicit state management. The state of “being logged in” is controlled by a cookie, and that cookie is sent with each request to a page. Unfortunately that includes requests triggered by 3rd party sites. If you don’t keep that in mind, some people might be able to trick your application’s users with social engineering to do stupid things without them knowing. Say you have a specific URL that, when you sent POST requests to will delete a user’s profile (say http://example.com/user/delete). If an attacker now creates a page that sends a post request to that page with some JavaScript they just have to trick some users to load that page and their profiles will end up being deleted. Imagine you were to run Facebook with millions of concurrent users and someone would send out links to images of little kittens. When users would go to that page, their profiles would get deleted while they are looking at images of fluffy cats. How can you prevent that? Basically for each request that modifies content on the server you would have to either use a one-time token and store that in the cookie and also transmit it with the form data. After receiving the data on the server again, you would then have to compare the two tokens and ensure they are equal. Why does Flask not do that for you? The ideal place for this to happen is the form validation framework, which does not exist in Flask. JSON Security¶ In Flask 0.10 and lower, jsonify() did not serialize top-level arrays to JSON. This was because of a security vulnerability in ECMAScript 4. ECMAScript 5 closed this vulnerability, so only extremely old browsers are still vulnerable. All of these browsers have other more serious vulnerabilities, so this behavior was changed and jsonify() now supports serializing arrays. Security Headers¶ Browsers recognize various response headers in order to control security. We recommend reviewing each of the headers below for use in your application. The Flask-Talisman extension can be used to manage HTTPS and the security headers for you. HTTP Strict Transport Security (HSTS)¶ Tells the browser to convert all HTTP requests to HTTPS, preventing man-in-the-middle (MITM) attacks. response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security Content Security Policy (CSP)¶ Tell the browser where it can load various types of resource from. This header should be used whenever possible, but requires some work to define the correct policy for your site. A very strict policy would ['Content-Security-Policy'] = \"default-src 'self'\" https://csp.withgoogle.com/docs/index.html https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy X-Content-Type-Options¶ Forces the browser to honor the response content type instead of trying to detect it, which can be abused to generate a cross-site scripting (XSS) attack. response.headers['X-Content-Type-Options'] = 'nosniff' https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options X-Frame-Options¶ Prevents external sites from embedding your site in an iframe. This prevents a class of attacks where clicks in the outer frame can be translated invisibly to clicks on your page’s elements. This is also known as “clickjacking”. response.headers['X-Frame-Options'] = 'SAMEORIGIN' https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options Set-Cookie options¶ These options can be added to a Set-Cookie header to improve their security. Flask has configuration options to set these on the session cookie. They can be set on other cookies too. Secure limits cookies to HTTPS traffic only. HttpOnly protects the contents of cookies from being read with JavaScript. SameSite restricts how cookies are sent with requests from external sites. Can be set to 'Lax' (recommended) or 'Strict'. Lax prevents sending cookies with CSRF-prone requests from external sites, such as submitting a form. Strict prevents sending cookies with all external requests, including following regular links. app.config.update( SESSION_COOKIE_SECURE=True, SESSION_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE='Lax', ) response.set_cookie('username', 'flask', secure=True, httponly=True, samesite='Lax') Specifying Expires or Max-Age options, will remove the cookie after the given time, or the current time plus the age, respectively. If neither option is set, the cookie will be removed when the browser is closed. # cookie expires after 10 minutes response.set_cookie('snakes', '3', max_age=600) For the session cookie, if session.permanent is set, then PERMANENT_SESSION_LIFETIME is used to set the expiration. Flask’s default cookie implementation validates that the cryptographic signature is not older than this value. Lowering this value may help mitigate replay attacks, where intercepted cookies can be sent at a later time. app.config.update( PERMANENT_SESSION_LIFETIME=600 ) @app.route('/login', methods=['POST']) def login(): ... session.clear() session['user_id'] = user.id session.permanent = True ... Use itsdangerous.TimedSerializer to sign and validate other cookie values (or any values that need secure signatures). https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie Host Header Validation¶ The Host header is used by the client to indicate what host name the request was made to. This is used, for example, by url_for(..., _external=True) to generate full URLs, for use in email or other messages outside the browser window. By default the app doesn’t know what host(s) it is allowed to be accessed through, and assumes any host is valid. Although browsers do not allow setting the Host header, requests made by attackers in other scenarios could set the Host header to a value they want. When deploying your application, set TRUSTED_HOSTS to restrict what values the Host header may be. The Host header may be modified by proxies in between the client and your application. See Tell Flask it is Behind a Proxy to tell your app which proxy values to trust. Copy/Paste to Terminal¶ Hidden characters such as the backspace character (\\b, ^H) can cause text to render differently in HTML than how it is interpreted if pasted into a terminal. For example, import y\\bose\\bm\\bi\\bt\\be\\b renders as import yosemite in HTML, but the backspaces are applied when pasted into a terminal, and it becomes import os. If you expect users to copy and paste untrusted code from your site, such as from comments posted by users on a technical blog, consider applying extra filtering, such as replacing all \\b characters. body = body.replace(\"\\b\", \"\") Most modern terminals will warn about and remove hidden characters when pasting, so this isn’t strictly necessary. It’s also possible to craft dangerous commands in other ways that aren’t possible to filter. Depending on your site’s use case, it may be good to show a warning about copying code in general. Contents Security Considerations Resource Use Cross-Site Scripting (XSS) Cross-Site Request Forgery (CSRF) JSON Security Security Headers HTTP Strict Transport Security (HSTS) Content Security Policy (CSP) X-Content-Type-Options X-Frame-Options Set-Cookie options Host Header Validation Copy/Paste to Terminal Navigation Overview Applications to Production Quick search\n\nExample:\n```text\n<input value=\"{{ value }}\">\n```\n\nExample:\n```text\nonmouseover=alert(document.cookie)\n```\n\nExample:\n```text\nresponse.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'\n```\n\nExample:\n```text\nresponse.headers['Content-Security-Policy'] = \"default-src 'self'\"\n```\n\nExample:\n```text\nresponse.headers['X-Content-Type-Options'] = 'nosniff'\n```\n\nExample:\n```text\nresponse.headers['X-Frame-Options'] = 'SAMEORIGIN'\n```\n\nExample:\n```text\napp.config.update(\n    SESSION_COOKIE_SECURE=True,\n    SESSION_COOKIE_HTTPONLY=True,\n    SESSION_COOKIE_SAMESITE='Lax',\n)\n\nresponse.set_cookie('username', 'flask', secure=True, httponly=True, samesite='Lax')\n```\n\nExample:\n```text\n# cookie expires after 10 minutes\nresponse.set_cookie('snakes', '3', max_age=600)\n```\n\nExample:\n```text\napp.config.update(\n    PERMANENT_SESSION_LIFETIME=600\n)\n\n@app.route('/login', methods=['POST'])\ndef login():\n    ...\n    session.clear()\n    session['user_id'] = user.id\n    session.permanent = True\n    ...\n```\n\nExample:\n```text\nbody = body.replace(\"\\b\", \"\")\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.729Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":10,"totalLines":70,"estimatedTokens":3259}}4{"id":"doc-flask_extension_development_flask_documentation_-8c0f4ba4","source":"documentation","title":"Flask Extension Development — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/extensiondev/","text":"Flask Extension Development¶ Extensions are extra packages that add functionality to a Flask application. While PyPI contains many Flask extensions, you may not find one that fits your need. If this is the case, you can create your own, and publish it for others to use as well. This guide will show how to create a Flask extension, and some of the common patterns and requirements involved. Since extensions can do anything, this guide won’t be able to cover every possibility. The best ways to learn about extensions are to look at how other extensions you use are written, and discuss with others. Discuss your design ideas with others on our Discord Chat or GitHub Discussions. The best extensions share common patterns, so that anyone familiar with using one extension won’t feel completely lost with another. This can only work if collaboration happens early. Naming¶ A Flask extension typically has flask in its name as a prefix or suffix. If it wraps another library, it should include the library name as well. This makes it easy to search for extensions, and makes their purpose clearer. A general Python packaging recommendation is that the install name from the package index and the name used in import statements should be related. The import name is lowercase, with words separated by underscores (_). The install name is either lower case or title case, with words separated by dashes (-). If it wraps another library, prefer using the same case as that library’s name. Here are some example install and import imported as flask_name flask-name-lower imported as flask_name_lower Flask-ComboName imported as flask_comboname Name-Flask imported as name_flask The Extension Class and Initialization¶ All extensions will need some entry point that initializes the extension with the application. The most common pattern is to create a class that represents the extension’s configuration and behavior, with an init_app method to apply the extension instance to the given application instance. class __init__(self, app=None): if app is not (app) def init_app(self, app): app.before_request(...) It is important that the app is not stored on the extension, don’t do self.app = app. The only time the extension should have direct access to an app is during init_app, otherwise it should use current_app. This allows the extension to support the application factory pattern, avoids circular import issues when importing the extension instance elsewhere in a user’s code, and makes testing with different configurations easier. hello = HelloExtension() def create_app(): app = Flask(__name__) hello.init_app(app) return app Above, the hello extension instance exists independently of the application. This means that other modules in a user’s project can do from project import hello and use the extension in blueprints before the app exists. The Flask.extensions dict can be used to store a reference to the extension on the application, or some other state specific to the application. Be aware that this is a single namespace, so use a name unique to your extension, such as the extension’s name without the “flask” prefix. Adding Behavior¶ There are many ways that an extension can add behavior. Any setup methods that are available on the Flask object can be used during an extension’s init_app method. A common pattern is to use before_request() to initialize some data or a connection at the beginning of each request, then teardown_request() to clean it up at the end. This can be stored on g, discussed more below. A more lazy approach is to provide a method that initializes and caches the data or connection. For example, a ext.get_db method could create a database connection the first time it’s called, so that a view that doesn’t use the database doesn’t create a connection. Besides doing something before and after every view, your extension might want to add some specific views as well. In this case, you could define a Blueprint, then call register_blueprint() during init_app to add the blueprint to the app. Configuration Techniques¶ There can be multiple levels and sources of configuration for an extension. You should consider what parts of your extension fall into each one. Configuration per application instance, through app.config values. This is configuration that could reasonably change for each deployment of an application. A common example is a URL to an external resource, such as a database. Configuration keys should start with the extension’s name so that they don’t interfere with other extensions. Configuration per extension instance, through __init__ arguments. This configuration usually affects how the extension is used, such that it wouldn’t make sense to change it per deployment. Configuration per extension instance, through instance attributes and decorator methods. It might be more ergonomic to assign to ext.value, or use a @ext.register decorator to register a function, after the extension instance has been created. Global configuration through class attributes. Changing a class attribute like Ext.connection_class can customize default behavior without making a subclass. This could be combined per-extension configuration to override defaults. Subclassing and overriding methods and attributes. Making the API of the extension itself something that can be overridden provides a very powerful tool for advanced customization. The Flask object itself uses all of these techniques. It’s up to you to decide what configuration is appropriate for your extension, based on what you need and what you want to support. Configuration should not be changed after the application setup phase is complete and the server begins handling requests. Configuration is global, any changes to it are not guaranteed to be visible to other workers. Data During a Request¶ When writing a Flask application, the g object is used to store information during a request. For example the tutorial stores a connection to a SQLite database as g.db. Extensions can also use this, with some care. Since g is a single global namespace, extensions must use unique names that won’t collide with user data. For example, use the extension name as a prefix, or as a namespace. # an internal prefix with the extension name g._hello_user_id = 2 # or an internal prefix as a namespace from types import SimpleNamespace g._hello = SimpleNamespace() g._hello.user_id = 2 The data in g lasts for an application context. An application context is active when a request context is, or when a CLI command is run. If you’re storing something that should be closed, use teardown_appcontext() to ensure that it gets closed when the application context ends. If it should only be valid during a request, or would not be used in the CLI outside a request, use teardown_request(). Views and Models¶ Your extension views might want to interact with specific models in your database, or some other extension or data connected to your application. For example, let’s consider a Flask-SimpleBlog extension that works with Flask-SQLAlchemy to provide a Post model and views to write and read posts. The Post model needs to subclass the Flask-SQLAlchemy db.Model object, but that’s only available once you’ve created an instance of that extension, not when your extension is defining its views. So how can the view code, defined before the model exists, access the model? One method could be to use Class-based Views. During __init__, create the model, then create the views by passing the model to the view class’s as_view() method. class PostAPI(MethodView): def __init__(self, model): self.model = model def get(self, id): post = self.model.query.get(id) return jsonify(post.to_json()) class __init__(self, db): class Post(db.Model): id = db.Column(primary_key=True) title = db.Column(db.String, nullable=False) self.post_model = Post def init_app(self, app): api_view = PostAPI.as_view(model=self.post_model) db = SQLAlchemy() blog = BlogExtension(db) db.init_app(app) blog.init_app(app) Another technique could be to use an attribute on the extension, such as self.post_model from above. Add the extension to app.extensions in init_app, then access current_app.extensions[\"simple_blog\"].post_model from views. You may also want to provide base classes so that users can provide their own Post model that conforms to the API your extension expects. So they could implement class Post(blog.BasePost), then set it as blog.post_model. As you can see, this can get a bit complex. Unfortunately, there’s no perfect solution here, only different strategies and tradeoffs depending on your needs and how much customization you want to offer. Luckily, this sort of resource dependency is not a common need for most extensions. Remember, if you need help with design, ask on our Discord Chat or GitHub Discussions. Recommended Extension Guidelines¶ Flask previously had the concept of “approved extensions”, where the Flask maintainers evaluated the quality, support, and compatibility of the extensions before listing them. While the list became too difficult to maintain over time, the guidelines are still relevant to all extensions maintained and developed today, as they help the Flask ecosystem remain consistent and compatible. An extension requires a maintainer. In the event an extension author would like to move beyond the project, the project should find a new maintainer and transfer access to the repository, documentation, PyPI, and any other services. The Pallets-Eco organization on GitHub allows for community maintenance with oversight from the Pallets maintainers. The naming scheme is Flask-ExtensionName or ExtensionName-Flask. It must provide exactly one package or module named flask_extension_name. The extension must use an open source license. The Python web ecosystem tends to prefer BSD or MIT. It must be open source and publicly available. The extension’s API must have the following must support multiple applications running in the same Python process. Use current_app instead of self.app, store configuration and state per application instance. It must be possible to use the factory pattern for creating applications. Use the ext.init_app() pattern. From a clone of the repository, an extension with its dependencies must be installable in editable mode with pip install -e .. It must ship tests that can be invoked with a common tool like tox -e py, nox -s test or pytest. If not using tox, the test dependencies should be specified in a requirements file. The tests must be part of the sdist distribution. A link to the documentation or project website must be in the PyPI metadata or the readme. The documentation should use the Flask theme from the Official Pallets Themes. The extension’s dependencies should not use upper bounds or assume any particular version scheme, but should use lower bounds to indicate minimum compatibility support. For example, sqlalchemy>=1.4. Indicate the versions of Python supported using python_requires=\">=version\". Flask itself supports Python >=3.9 as of October 2024, and this will update over time. Contents Flask Extension Development Naming The Extension Class and Initialization Adding Behavior Configuration Techniques Data During a Request Views and Models Recommended Extension Guidelines Navigation Overview Decisions in Flask Quick search\n\nExample:\n```text\nclass HelloExtension:\n    def __init__(self, app=None):\n        if app is not None:\n            self.init_app(app)\n\n    def init_app(self, app):\n        app.before_request(...)\n```\n\nExample:\n```text\nhello = HelloExtension()\n\ndef create_app():\n    app = Flask(__name__)\n    hello.init_app(app)\n    return app\n```\n\nExample:\n```text\n# an internal prefix with the extension name\ng._hello_user_id = 2\n\n# or an internal prefix as a namespace\nfrom types import SimpleNamespace\ng._hello = SimpleNamespace()\ng._hello.user_id = 2\n```\n\nExample:\n```text\nclass PostAPI(MethodView):\n    def __init__(self, model):\n        self.model = model\n\n    def get(self, id):\n        post = self.model.query.get(id)\n        return jsonify(post.to_json())\n\nclass BlogExtension:\n    def __init__(self, db):\n        class Post(db.Model):\n            id = db.Column(primary_key=True)\n            title = db.Column(db.String, nullable=False)\n\n        self.post_model = Post\n\n    def init_app(self, app):\n        api_view = PostAPI.as_view(model=self.post_model)\n\ndb = SQLAlchemy()\nblog = BlogExtension(db)\ndb.init_app(app)\nblog.init_app(app)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.732Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":62,"estimatedTokens":3119}}5{"id":"doc-tell_flask_it_is_behind_a_proxy_flask_documentat-1fed8060","source":"documentation","title":"Tell Flask it is Behind a Proxy — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/proxy_fix/","text":"Tell Flask it is Behind a Proxy¶ When using a reverse proxy, or many Python hosting platforms, the proxy will intercept and forward all external requests to the local WSGI server. From the WSGI server and Flask application’s perspectives, requests are now coming from the HTTP server to the local address, rather than from the remote address to the external server address. HTTP servers should set X-Forwarded- headers to pass on the real values to the application. The application can then be told to trust and use those values by wrapping it with the X-Forwarded-For Proxy Fix middleware provided by Werkzeug. This middleware should only be used if the application is actually behind a proxy, and should be configured with the number of proxies that are chained in front of it. Not all proxies set all the headers. Since incoming headers can be faked, you must set how many proxies are setting each header so the middleware knows what to trust. from werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app = ProxyFix( app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1 ) Remember, only apply this middleware if you are behind a proxy, and set the correct number of proxies that set each header. It can be a security issue if you get this configuration wrong. Navigation Overview Deploying to Production Quick search\n\nExample:\n```text\nfrom werkzeug.middleware.proxy_fix import ProxyFix\n\napp.wsgi_app = ProxyFix(\n    app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1\n)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.734Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":1,"totalLines":12,"estimatedTokens":375}}6{"id":"doc-asgi_flask_documentation_3_1_x-653e98a7","source":"documentation","title":"ASGI — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/asgi/","text":"ASGI¶ If you’d like to use an ASGI server you will need to utilise WSGI to ASGI middleware. The asgiref WsgiToAsgi adapter is recommended as it integrates with the event loop used for Flask’s Using async and await support. You can use the adapter by wrapping the Flask app, from asgiref.wsgi import WsgiToAsgi from flask import Flask app = Flask(__name__) ... asgi_app = WsgiToAsgi(app) and then serving the asgi_app with the ASGI server, e.g. using Hypercorn, $ hypercorn Navigation Overview Deploying to Production Flask it is Behind a Proxy Quick search\n\nExample:\n```text\nfrom asgiref.wsgi import WsgiToAsgi\nfrom flask import Flask\n\napp = Flask(__name__)\n\n...\n\nasgi_app = WsgiToAsgi(app)\n```\n\nExample:\n```text\n$ hypercorn module:asgi_app\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.734Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":20,"estimatedTokens":190}}7{"id":"doc-adding_a_favicon_flask_documentation_3_1_x-367135be","source":"documentation","title":"Adding a favicon — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/favicon/","text":"Adding a favicon¶ A “favicon” is an icon used by browsers for tabs and bookmarks. This helps to distinguish your website and to give it a unique brand. A common question is how to add a favicon to a Flask application. First, of course, you need an icon. It should be 16 × 16 pixels and in the ICO file format. This is not a requirement but a de-facto standard supported by all relevant browsers. Put the icon in your static directory as favicon.ico. Now, to get browsers to find your icon, the correct way is to add a link tag in your HTML. So, for example: <link rel=\"shortcut icon\" href=\"{{ url_for('static', filename='favicon.ico') }}\"> That’s all you need for most browsers, however some really old ones do not support this standard. The old de-facto standard is to serve this file, with this name, at the website root. If your application is not mounted at the root path of the domain you either need to configure the web server to serve the icon at the root or if you can’t do that you’re out of luck. If however your application is the root you can simply route a ( \"/favicon.ico\", endpoint=\"favicon\", redirect_to=url_for(\"static\", filename=\"favicon.ico\"), ) If you want to save the extra redirect request you can also write a view using send_from_directory(): import os from flask import send_from_directory @app.route('/favicon.ico') def favicon(): return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon') We can leave out the explicit mimetype and it will be guessed, but we may as well specify it to avoid the extra guessing, as it will always be the same. The above will serve the icon via your application and if possible it’s better to configure your dedicated web server to serve it; refer to the web server’s documentation. See also¶ The Favicon article on Wikipedia Contents Adding a favicon See also Navigation Overview Patterns for Flask with MongoEngine Contents Quick search\n\nExample:\n```text\n<link rel=\"shortcut icon\" href=\"{{ url_for('static', filename='favicon.ico') }}\">\n```\n\nExample:\n```text\napp.add_url_rule(\n    \"/favicon.ico\",\n    endpoint=\"favicon\",\n    redirect_to=url_for(\"static\", filename=\"favicon.ico\"),\n)\n```\n\nExample:\n```text\nimport os\nfrom flask import send_from_directory\n\n@app.route('/favicon.ico')\ndef favicon():\n    return send_from_directory(os.path.join(app.root_path, 'static'),\n                               'favicon.ico', mimetype='image/vnd.microsoft.icon')\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.735Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":3,"totalLines":28,"estimatedTokens":622}}8{"id":"doc-waitress_flask_documentation_3_1_x-06295f7a","source":"documentation","title":"Waitress — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/waitress/","text":"Waitress¶ Waitress is a pure Python WSGI server. It is easy to configure. It supports Windows directly. It is easy to install as it does not require additional dependencies or compilation. It does not support streaming requests, full request data is always buffered. It uses a single process with multiple thread workers. This page outlines the basics of running Waitress. Be sure to read its documentation and waitress-serve --help to understand what features are available. Installing¶ Create a virtualenv, install your application, then install waitress. $ cd hello-app $ python -m venv :{app}. module is the dotted import name to the module with your application. app is the variable with the application. If you’re using the app factory pattern, use --call {module}:{factory} instead. # equivalent to 'from hello import app' $ waitress-serve --host 127.0.0.1 # equivalent to 'from hello import create_app; create_app()' $ waitress-serve --host 127.0.0.1 --call Serving on http://127.0.0.1:8080 The --host option binds the server to local 127.0.0.1 only. Logs for each request aren’t shown, only errors are shown. Logging can be configured through the Python interface instead of the command line. Binding Externally¶ Waitress should not be run as root because it would cause your application code to run as root, which is not secure. However, this means it will not be possible to bind to port 80 or 443. Instead, a reverse proxy such as nginx or Apache httpd should be used in front of Waitress. You can bind to all external IPs on a non-privileged port by not specifying the --host option. Don’t do this when using a reverse proxy setup, otherwise it will be possible to bypass the proxy. 0.0.0.0 is not a valid address to navigate to, you’d use a specific IP address in your browser. Contents Waitress Installing Running Binding Externally Navigation Overview Deploying to Production Quick search\n\nExample:\n```text\n$ cd hello-app\n$ python -m venv .venv\n$ . .venv/bin/activate\n$ pip install .  # install your application\n$ pip install waitress\n```\n\nExample:\n```text\n# equivalent to 'from hello import app'\n$ waitress-serve --host 127.0.0.1 hello:app\n\n# equivalent to 'from hello import create_app; create_app()'\n$ waitress-serve --host 127.0.0.1 --call hello:create_app\n\nServing on http://127.0.0.1:8080\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.735Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":23,"estimatedTokens":582}}9{"id":"doc-gunicorn_flask_documentation_3_1_x-a7cbdd46","source":"documentation","title":"Gunicorn — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/gunicorn/","text":"Gunicorn¶ Gunicorn is a pure Python WSGI server with simple configuration and multiple worker implementations for performance tuning. It tends to integrate easily with hosting platforms. It does not support Windows (but does run on WSL). It is easy to install as it does not require additional dependencies or compilation. It has built-in async worker support using gevent. This page outlines the basics of running Gunicorn. Be sure to read its documentation and use gunicorn --help to understand what features are available. Installing¶ Gunicorn is easy to install, as it does not require external dependencies or compilation. It runs on Windows only under WSL. Create a virtualenv, install your application, then install gunicorn. $ cd hello-app $ python -m venv :{app_variable}. module_import is the dotted import name to the module with your application. app_variable is the variable with the application. It can also be a function call (with any arguments) if you’re using the app factory pattern. # equivalent to 'from hello import app' $ gunicorn -w 4 'hello:app' # equivalent to 'from hello import create_app; create_app()' $ gunicorn -w 4 'hello:create_app()' Starting gunicorn 20.1.0 Listening ://127.0.0.1:8000 (x) Using Booting worker with Booting worker with Booting worker with Booting worker with The -w option specifies the number of processes to run; a starting value could be CPU * 2. The default is only 1 worker, which is probably not what you want for the default worker type. Logs for each request aren’t shown by default, only worker info and errors are shown. To show access logs on stdout, use the --access-logfile=- option. Binding Externally¶ Gunicorn should not be run as root because it would cause your application code to run as root, which is not secure. However, this means it will not be possible to bind to port 80 or 443. Instead, a reverse proxy such as nginx or Apache httpd should be used in front of Gunicorn. You can bind to all external IPs on a non-privileged port using the -b 0.0.0.0 option. Don’t do this when using a reverse proxy setup, otherwise it will be possible to bypass the proxy. $ gunicorn -w 4 -b 0.0.0.0 'hello:create_app()' Listening ://0.0.0.0:8000 (x) 0.0.0.0 is not a valid address to navigate to, you’d use a specific IP address in your browser. Async with gevent¶ The default sync worker is appropriate for most use cases. If you need numerous, long running, concurrent connections, Gunicorn provides an asynchronous worker using gevent. This is not the same as Python’s async/await, or the ASGI server spec. See Async with Gevent for more information about enabling it in your application. When using gevent, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is required. $ gunicorn -k gevent 'hello:create_app()' Starting gunicorn 20.1.0 Listening ://127.0.0.1:8000 (x) Using Booting worker with Contents Gunicorn Installing Running Binding Externally Async with gevent Navigation Overview Deploying to Production to Production Quick search\n\nExample:\n```text\n$ cd hello-app\n$ python -m venv .venv\n$ . .venv/bin/activate\n$ pip install .  # install your application\n$ pip install gunicorn\n```\n\nExample:\n```text\n# equivalent to 'from hello import app'\n$ gunicorn -w 4 'hello:app'\n\n# equivalent to 'from hello import create_app; create_app()'\n$ gunicorn -w 4 'hello:create_app()'\n\nStarting gunicorn 20.1.0\nListening at: http://127.0.0.1:8000 (x)\nUsing worker: sync\nBooting worker with pid: x\nBooting worker with pid: x\nBooting worker with pid: x\nBooting worker with pid: x\n```\n\nExample:\n```text\n$ gunicorn -w 4 -b 0.0.0.0 'hello:create_app()'\nListening at: http://0.0.0.0:8000 (x)\n```\n\nExample:\n```text\n$ gunicorn -k gevent 'hello:create_app()'\nStarting gunicorn 20.1.0\nListening at: http://127.0.0.1:8000 (x)\nUsing worker: gevent\nBooting worker with pid: x\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.735Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":44,"estimatedTokens":961}}10{"id":"doc-apache_httpd_flask_documentation_3_1_x-161d9c6b","source":"documentation","title":"Apache httpd — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/apache-httpd/","text":"Apache httpd¶ Apache httpd is a fast, production level HTTP server. When serving your application with one of the WSGI servers listed in Deploying to Production, it is often good or necessary to put a dedicated HTTP server in front of it. This “reverse proxy” can handle incoming requests, TLS, and other security and performance concerns better than the WSGI server. httpd can be installed using your system package manager, or a pre-built executable for Windows. Installing and running httpd itself is outside the scope of this doc. This page outlines the basics of configuring httpd to proxy your application. Be sure to read its documentation to understand what features are available. Domain Name¶ Acquiring and configuring a domain name is outside the scope of this doc. In general, you will buy a domain name from a registrar, pay for server space with a hosting provider, and then point your registrar at the hosting provider’s name servers. To simulate this, you can also edit your hosts file, located at /etc/hosts on Linux. Add a line that associates a name with the local IP. Modern Linux systems may be configured to treat any domain name that ends with .localhost like this without adding it to the hosts file. /etc/hosts¶ 127.0.0.1 hello.localhost Configuration¶ The httpd configuration is located at /etc/httpd/conf/httpd.conf on Linux. It may be different depending on your operating system. Check the docs and look for httpd.conf. Remove or comment out any existing DocumentRoot directive. Add the config lines below. We’ll assume the WSGI server is listening locally at http://127.0.0.1:8000. /etc/httpd/conf/httpd.conf¶ LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so ProxyPass / http://127.0.0.1:8000/ RequestHeader set X-Forwarded-Proto http RequestHeader set X-Forwarded-Prefix / The LoadModule lines might already exist. If so, make sure they are uncommented instead of adding them manually. Then Tell Flask it is Behind a Proxy so that your application uses the X-Forwarded headers. X-Forwarded-For and X-Forwarded-Host are automatically set by ProxyPass. Contents Apache httpd Domain Name Configuration Navigation Overview Deploying to Production with Gevent Quick search\n\nExample:\n```text\n127.0.0.1 hello.localhost\n```\n\nExample:\n```text\nLoadModule proxy_module modules/mod_proxy.so\nLoadModule proxy_http_module modules/mod_proxy_http.so\nProxyPass / http://127.0.0.1:8000/\nRequestHeader set X-Forwarded-Proto http\nRequestHeader set X-Forwarded-Prefix /\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.736Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":17,"estimatedTokens":637}}11{"id":"doc-nginx_flask_documentation_3_1_x-74e97068","source":"documentation","title":"nginx — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/nginx/","text":"nginx¶ nginx is a fast, production level HTTP server. When serving your application with one of the WSGI servers listed in Deploying to Production, it is often good or necessary to put a dedicated HTTP server in front of it. This “reverse proxy” can handle incoming requests, TLS, and other security and performance concerns better than the WSGI server. Nginx can be installed using your system package manager, or a pre-built executable for Windows. Installing and running Nginx itself is outside the scope of this doc. This page outlines the basics of configuring Nginx to proxy your application. Be sure to read its documentation to understand what features are available. Domain Name¶ Acquiring and configuring a domain name is outside the scope of this doc. In general, you will buy a domain name from a registrar, pay for server space with a hosting provider, and then point your registrar at the hosting provider’s name servers. To simulate this, you can also edit your hosts file, located at /etc/hosts on Linux. Add a line that associates a name with the local IP. Modern Linux systems may be configured to treat any domain name that ends with Then Tell Flask it is Behind a Proxy so that your application uses these headers. Contents nginx Domain Name Configuration Navigation Overview Deploying to Production Flask it is Behind a Proxy httpd Quick search\n\nExample:\n```text\n127.0.0.1 hello.localhost\n```\n\nExample:\n```text\nserver {\n    listen 80;\n    server_name _;\n\n    location / {\n        proxy_pass http://127.0.0.1:8000/;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header X-Forwarded-Host $host;\n        proxy_set_header X-Forwarded-Prefix /;\n    }\n}\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.736Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":24,"estimatedTokens":445}}12{"id":"doc-uwsgi_flask_documentation_3_1_x-3ef06aa6","source":"documentation","title":"uWSGI — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/uwsgi/","text":"uWSGI¶ uWSGI is a fast, compiled server suite with extensive configuration and capabilities beyond a basic server. It can be very performant due to being a compiled program. It is complex to configure beyond the basic application, and has so many options that it can be difficult for beginners to understand. It does not support Windows (but does run on WSL). It requires a compiler to install in some cases. This page outlines the basics of running uWSGI. Be sure to read its documentation to understand what features are available. Installing¶ uWSGI has multiple ways to install it. The most straightforward is to install the pyuwsgi package, which provides precompiled wheels for common platforms. However, it does not provide SSL support, which can be provided with a reverse proxy instead. Create a virtualenv, install your application, then install pyuwsgi. $ cd hello-app $ python -m venv .venv $ . .venv/bin/activate $ pip install . # install your application $ pip install pyuwsgi If you have a compiler available, you can install the uwsgi package instead. Or install the pyuwsgi package from sdist instead of wheel. Either method will include SSL support. $ pip install uwsgi # or $ pip install --no-binary pyuwsgi pyuwsgi Running¶ The most basic way to run uWSGI is to tell it to start an HTTP server and import your application. $ uwsgi --http 127.0.0.1:8000 --master -p 4 -w *** Starting uWSGI 2.0.20 (64bit) on [x] *** *** Operational *** mounting on / spawned uWSGI master process (pid: x) spawned uWSGI worker 1 (pid: x, ) spawned uWSGI worker 2 (pid: x, ) spawned uWSGI worker 3 (pid: x, ) spawned uWSGI worker 4 (pid: x, ) spawned uWSGI http 1 (pid: x) If you’re using the app factory pattern, you’ll need to create a small Python file to create the app, then point uWSGI at that. wsgi.py¶ from hello import create_app app = create_app() $ uwsgi --http 127.0.0.1:8000 --master -p 4 -w The --http option starts an HTTP server at 127.0.0.1 port 8000. The --master option specifies the standard worker manager. The -p option starts 4 worker processes; a starting value could be CPU * 2. The -w option tells uWSGI how to import your application Binding Externally¶ uWSGI should not be run as root with the configuration shown in this doc because it would cause your application code to run as root, which is not secure. However, this means it will not be possible to bind to port 80 or 443. Instead, a reverse proxy such as nginx or Apache httpd should be used in front of uWSGI. It is possible to run uWSGI as root securely, but that is beyond the scope of this doc. uWSGI has optimized integration with Nginx uWSGI and Apache mod_proxy_uwsgi, and possibly other servers, instead of using a standard HTTP proxy. That configuration is beyond the scope of this doc, see the links for more information. You can bind to all external IPs on a non-privileged port using the --http 0.0.0.0:8000 option. Don’t do this when using a reverse proxy setup, otherwise it will be possible to bypass the proxy. $ uwsgi --http 0.0.0.0:8000 --master -p 4 -w 0.0.0.0 is not a valid address to navigate to, you’d use a specific IP address in your browser. Async with gevent¶ The default sync worker is appropriate for most use cases. If you need numerous, long running, concurrent connections, uWSGI provides an asynchronous worker using gevent. This is not the same as Python’s async/await, or the ASGI server spec. See Async with Gevent for more information about enabling it in your application. When using gevent, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is required. $ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w *** Starting uWSGI 2.0.20 (64bit) on [x] *** *** Operational *** mounting on / spawned uWSGI master process (pid: x) spawned uWSGI worker 1 (pid: x, ) spawned uWSGI http 1 (pid: x) *** running gevent loop engine [addr:x] *** Contents uWSGI Installing Running Binding Externally Async with gevent Navigation Overview Deploying to Production Quick search\n\nExample:\n```text\n$ cd hello-app\n$ python -m venv .venv\n$ . .venv/bin/activate\n$ pip install .  # install your application\n$ pip install pyuwsgi\n```\n\nExample:\n```text\n$ pip install uwsgi\n\n# or\n$ pip install --no-binary pyuwsgi pyuwsgi\n```\n\nExample:\n```text\n$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app\n\n*** Starting uWSGI 2.0.20 (64bit) on [x] ***\n*** Operational MODE: preforking ***\nmounting hello:app on /\nspawned uWSGI master process (pid: x)\nspawned uWSGI worker 1 (pid: x, cores: 1)\nspawned uWSGI worker 2 (pid: x, cores: 1)\nspawned uWSGI worker 3 (pid: x, cores: 1)\nspawned uWSGI worker 4 (pid: x, cores: 1)\nspawned uWSGI http 1 (pid: x)\n```\n\nExample:\n```text\nfrom hello import create_app\n\napp = create_app()\n```\n\nExample:\n```text\n$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app\n```\n\nExample:\n```text\n$ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app\n```\n\nExample:\n```text\n$ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app\n\n*** Starting uWSGI 2.0.20 (64bit) on [x] ***\n*** Operational MODE: async ***\nmounting hello:app on /\nspawned uWSGI master process (pid: x)\nspawned uWSGI worker 1 (pid: x, cores: 100)\nspawned uWSGI http 1 (pid: x)\n*** running gevent loop engine [addr:x] ***\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.737Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":65,"estimatedTokens":1309}}13{"id":"doc-gevent_flask_documentation_3_1_x-eca35263","source":"documentation","title":"gevent — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/gevent/","text":"gevent¶ Prefer using Gunicorn or uWSGI with gevent workers rather than using gevent directly. Gunicorn and uWSGI provide much more configurable and production-tested servers. gevent allows writing asynchronous, coroutine-based code that looks like standard synchronous Python. It uses greenlet to enable task switching without writing async/await or using asyncio. This is not the same as Python’s async/await, or the ASGI server spec. gevent provides a WSGI server that can handle many connections at once instead of one per worker process. See Async with Gevent for more information about enabling it in your application. Installing¶ When using gevent, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is required. Create a virtualenv, install your application, then install gevent. $ cd hello-app $ python -m venv .venv $ . .venv/bin/activate $ pip install . # install your application $ pip install gevent Running¶ To use gevent to serve your application, write a script that imports its WSGIServer, as well as your app or app factory. wsgi.py¶ from gevent.pywsgi import WSGIServer from hello import create_app app = create_app() http_server = WSGIServer((\"127.0.0.1\", 8000), app) http_server.serve_forever() $ python wsgi.py No output is shown when the server starts. Binding Externally¶ gevent should not be run as root because it would cause your application code to run as root, which is not secure. However, this means it will not be possible to bind to port 80 or 443. Instead, a reverse proxy such as nginx or Apache httpd should be used in front of gevent. You can bind to all external IPs on a non-privileged port by using 0.0.0.0 in the server arguments shown in the previous section. Don’t do this when using a reverse proxy setup, otherwise it will be possible to bypass the proxy. 0.0.0.0 is not a valid address to navigate to, you’d use a specific IP address in your browser. Contents gevent Installing Running Binding Externally Navigation Overview Deploying to Production Quick search\n\nExample:\n```text\n$ cd hello-app\n$ python -m venv .venv\n$ . .venv/bin/activate\n$ pip install .  # install your application\n$ pip install gevent\n```\n\nExample:\n```text\nfrom gevent.pywsgi import WSGIServer\nfrom hello import create_app\n\napp = create_app()\nhttp_server = WSGIServer((\"127.0.0.1\", 8000), app)\nhttp_server.serve_forever()\n```\n\nExample:\n```text\n$ python wsgi.py\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.737Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":3,"totalLines":27,"estimatedTokens":600}}14{"id":"doc-mod_wsgi_flask_documentation_3_1_x-f6beb2f6","source":"documentation","title":"mod_wsgi — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/mod_wsgi/","text":"mod_wsgi¶ mod_wsgi is a WSGI server integrated with the Apache httpd server. The modern mod_wsgi-express command makes it easy to configure and start the server without needing to write Apache httpd configuration. Tightly integrated with Apache httpd. Supports Windows directly. Requires a compiler and the Apache development headers to install. Does not require a reverse proxy setup. This page outlines the basics of running mod_wsgi-express, not the more complex installation and configuration with httpd. Be sure to read the mod_wsgi-express, mod_wsgi, and Apache httpd documentation to understand what features are available. Installing¶ Installing mod_wsgi requires a compiler and the Apache server and development headers installed. You will get an error if they are not. How to install them depends on the OS and package manager that you use. Create a virtualenv, install your application, then install mod_wsgi. $ cd hello-app $ python -m venv .venv $ . .venv/bin/activate $ pip install . # install your application $ pip install mod_wsgi Running¶ The only argument to mod_wsgi-express specifies a script containing your Flask application, which must be called application. You can write a small script to import your app with this name, or to create it if using the app factory pattern. wsgi.py¶ from hello import app application = app wsgi.py¶ from hello import create_app application = create_app() Now run the mod_wsgi-express start-server command. $ mod_wsgi-express start-server wsgi.py --processes 4 The --processes option specifies the number of worker processes to run; a starting value could be CPU * 2. Logs for each request aren’t show in the terminal. If an error occurs, its information is written to the error log file shown when starting the server. Binding Externally¶ Unlike the other WSGI servers in these docs, mod_wsgi can be run as root to bind to privileged ports like 80 and 443. However, it must be configured to drop permissions to a different user and group for the worker processes. For example, if you created a hello user and group, you should install your virtualenv and application as that user, then tell mod_wsgi to drop to that user after starting. $ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \\ /home/hello/wsgi.py \\ --user hello --group hello --port 80 --processes 4 Contents mod_wsgi Installing Running Binding Externally Navigation Overview Deploying to Production Quick search\n\nExample:\n```text\n$ cd hello-app\n$ python -m venv .venv\n$ . .venv/bin/activate\n$ pip install .  # install your application\n$ pip install mod_wsgi\n```\n\nExample:\n```text\nfrom hello import app\n\napplication = app\n```\n\nExample:\n```text\nfrom hello import create_app\n\napplication = create_app()\n```\n\nExample:\n```text\n$ mod_wsgi-express start-server wsgi.py --processes 4\n```\n\nExample:\n```text\n$ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \\\n    /home/hello/wsgi.py \\\n    --user hello --group hello --port 80 --processes 4\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.737Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":5,"totalLines":38,"estimatedTokens":747}}15{"id":"doc-changes_flask_documentation_3_1_x-f56de732","source":"documentation","title":"Changes — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/changes/","text":"Changes¶ Version 3.1.3¶ Released 2026-02-18 The session is marked as accessed for operations that only access the keys but not the values, such as in and len. GHSA-68rp-wp8r-4726 Version 3.1.2¶ Released 2025-08-19 stream_with_context does not fail inside async views. #5774 When using follow_redirects in the test client, the final state of session is correct. #5786 Relax type hint for passing bytes IO to send_file. #5776 Version 3.1.1¶ Released 2025-05-13 Fix signing key selection order when key rotation is enabled via SECRET_KEY_FALLBACKS. GHSA-4grg-w6v8-c28g Fix type hint for cli_runner.invoke. #5645 flask --help loads the app and plugins first to make sure all commands are shown. #5673 Mark sans-io base class as being able to handle views that return AsyncIterable. This is not accurate for Flask, but makes typing easier for Quart. #5659 Version 3.1.0¶ Released 2024-11-13 Drop support for Python 3.8. #5623 Update minimum dependency versions to latest feature releases. Werkzeug >= 3.1, ItsDangerous >= 2.2, Blinker >= 1.9. #5624,5633 Provide a configuration option to control automatic option responses. #5496 Flask.open_resource/open_instance_resource and Blueprint.open_resource take an encoding parameter to use when opening in text mode. It defaults to utf-8. #5504 Request.max_content_length can be customized per-request instead of only through the MAX_CONTENT_LENGTH config. Added MAX_FORM_MEMORY_SIZE and MAX_FORM_PARTS config. Added documentation about resource limits to the security page. #5625 Add support for the Partitioned cookie attribute (CHIPS), with the SESSION_COOKIE_PARTITIONED config. #5472 -e path takes precedence over default .env and .flaskenv files. load_dotenv loads default files in addition to a path unless load_defaults=False is passed. #5628 Support key rotation with the SECRET_KEY_FALLBACKS config, a list of old secret keys that can still be used for unsigning. Extensions will need to add support. #5621 Fix how setting host_matching=True or subdomain_matching=False interacts with SERVER_NAME. Setting SERVER_NAME no longer restricts requests to only that domain. #5553 Request.trusted_hosts is checked during routing, and can be set through the TRUSTED_HOSTS config. #5636 Version 3.0.3¶ Released 2024-04-07 The default hashlib.sha1 may not be available in FIPS builds. Don’t access it at import time so the developer has time to change the default. #5448 Don’t initialize the cli attribute in the sansio scaffold, but rather in the Flask concrete class. #5270 Version 3.0.2¶ Released 2024-02-03 Correct type for jinja_loader property. #5388 Fix error with --extra-files and --exclude-patterns CLI options. #5391 Version 3.0.1¶ Released 2024-01-18 Correct type for path argument to send_file. #5336 Fix a typo in an error message for the flask run --key option. #5344 Session data is untagged without relying on the built-in json.loads object_hook. This allows other JSON providers that don’t implement that. #5381 Address more type findings when using mypy strict mode. #5383 Version 3.0.0¶ Released 2023-09-30 Remove previously deprecated code. #5223 Deprecate the __version__ attribute. Use feature detection, or importlib.metadata.version(\"flask\"), instead. #5230 Restructure the code such that the Flask (app) and Blueprint classes have Sans-IO bases. #5127 Allow self as an argument to url_for. #5264 Require Werkzeug >= 3.0.0. Version 2.3.3¶ Released 2023-08-21 Python 3.12 compatibility. Require Werkzeug >= 2.3.7. Use flit_core instead of setuptools as build backend. Refactor how an app’s root and instance paths are determined. #5160 Version 2.3.2¶ Released 2023-05-01 Set header when the session is accessed, modified, or refreshed. Update Werkzeug requirement to >=2.3.3 to apply recent bug fixes. GHSA-m2qf-hxjv-5gpq Version 2.3.1¶ Released 2023-04-25 Restore deprecated from flask import Markup. #5084 Version 2.3.0¶ Released 2023-04-25 Drop support for Python 3.7. #5072 Update minimum requirements to the latest >=2.3.0, Jinja2>3.1.2, itsdangerous>=2.1.2, click>=8.1.3. Remove previously deprecated code. #4995 The push and pop methods of the deprecated _app_ctx_stack and _request_ctx_stack objects are removed. top still exists to give extensions more time to update, but it will be removed. The FLASK_ENV environment variable, ENV config key, and app.env property are removed. The session_cookie_name, send_file_max_age_default, use_x_sendfile, propagate_exceptions, and templates_auto_reload properties on app are removed. The JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, and JSONIFY_PRETTYPRINT_REGULAR config keys are removed. The app.before_first_request and bp.before_app_first_request decorators are removed. json_encoder and json_decoder attributes on app and blueprint, and the corresponding json.JSONEncoder and JSONDecoder classes, are removed. The json.htmlsafe_dumps and htmlsafe_dump functions are removed. Calling setup methods on blueprints after registration is an error instead of a warning. #4997 Importing escape and Markup from flask is deprecated. Import them directly from markupsafe instead. #4996 The app.got_first_request property is deprecated. #4997 The locked_cached_property decorator is deprecated. Use a lock inside the decorated function if locking is needed. #4993 Signals are always available. blinker>=1.6.2 is a required dependency. The signals_available attribute is deprecated. #5056 Signals support async subscriber functions. #5049 Remove uses of locks that could cause requests to block each other very briefly. #4993 Use modern packaging metadata with pyproject.toml instead of setup.cfg. #4947 Ensure subdomains are applied with nested blueprints. #4834 config.from_file can use text=False to indicate that the parser wants a binary file instead. #4989 If a blueprint is created with an empty name it raises a ValueError. #5010 SESSION_COOKIE_DOMAIN does not fall back to SERVER_NAME. The default is not to set the domain, which modern browsers interpret as an exact match rather than a subdomain match. Warnings about localhost and IP addresses are also removed. #5051 The routes command shows each rule’s subdomain or host when domain matching is in use. #5004 Use postponed evaluation of annotations. #5071 Version 2.2.5¶ Released 2023-05-02 Update for compatibility with Werkzeug 2.3.3. Set header when the session is accessed, modified, or refreshed. Version 2.2.4¶ Released 2023-04-25 Update for compatibility with Werkzeug 2.3. Version 2.2.3¶ Released 2023-02-15 Autoescape is enabled by default for .svg template files. #4831 Fix the type of template_folder to accept pathlib.Path. #4892 Add --debug option to the flask run command. #4777 Version 2.2.2¶ Released 2022-08-08 Update Werkzeug dependency to >= 2.2.2. This includes fixes related to the new faster router, header parsing, and the development server. #4754 Fix the default value for app.env to be \"production\". This attribute remains deprecated. #4740 Version 2.2.1¶ Released 2022-08-03 Setting or accessing json_encoder or json_decoder raises a deprecation warning. #4732 Version 2.2.0¶ Released 2022-08-01 Remove previously deprecated code. #4667 Old names for some send_file parameters have been removed. download_name replaces attachment_filename, max_age replaces cache_timeout, and etag replaces add_etags. Additionally, path replaces filename in send_from_directory. The RequestContext.g property returning AppContext.g is removed. Update Werkzeug dependency to >= 2.2. The app and request contexts are managed using Python context vars directly rather than Werkzeug’s LocalStack. This should result in better performance and memory use. #4682 Extension maintainers, be aware that _app_ctx_stack.top and _request_ctx_stack.top are deprecated. Store data on g instead using a unique prefix, like g._extension_name_attr. The FLASK_ENV environment variable and app.env attribute are deprecated, removing the distinction between development and debug mode. Debug mode should be controlled directly using the --debug option or app.run(debug=True). #4714 Some attributes that proxied config keys on app are , send_file_max_age_default, use_x_sendfile, propagate_exceptions, and templates_auto_reload. Use the relevant config keys instead. #4716 Add new customization points to the Flask app object for many previously global behaviors. flask.url_for will call app.url_for. #4568 flask.abort will call app.aborter. Flask.aborter_class and Flask.make_aborter can be used to customize this aborter. #4567 flask.redirect will call app.redirect. #4569 flask.json is an instance of JSONProvider. A different provider can be set to use a different JSON library. flask.jsonify will call app.json.response, other functions in flask.json will call corresponding functions in app.json. #4692 JSON configuration is moved to attributes on the default app.json provider. JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, and JSONIFY_PRETTYPRINT_REGULAR are deprecated. #4692 Setting custom json_encoder and json_decoder classes on the app or a blueprint, and the corresponding json.JSONEncoder and JSONDecoder classes, are deprecated. JSON behavior can now be overridden using the app.json provider interface. #4692 json.htmlsafe_dumps and json.htmlsafe_dump are deprecated, the function is built-in to Jinja now. #4692 Refactor register_error_handler to consolidate error checking. Rewrite some error messages to be more consistent. #4559 Use Blueprint decorators and functions intended for setup after registering the blueprint will show a warning. In the next version, this will become an error just like the application setup methods. #4571 before_first_request is deprecated. Run setup code when creating the application instead. #4605 Added the View.init_every_request class attribute. If a view subclass sets this to False, the view will not create a new instance on every request. #2520. A flask.cli.FlaskGroup Click group can be nested as a sub-command in a custom CLI. #3263 Add --app and --debug options to the flask CLI, instead of requiring that they are set through environment variables. #2836 Add --env-file option to the flask CLI. This allows specifying a dotenv file to load in addition to .env and .flaskenv. #3108 It is no longer required to decorate custom CLI commands on app.cli or blueprint.cli with @with_appcontext, an app context will already be active at that point. #2410 SessionInterface.get_expiration_time uses a timezone-aware value. #4645 View functions can return generators directly instead of wrapping them in a Response. #4629 Add stream_template and stream_template_string functions to render a template as a stream of pieces. #4629 A new implementation of context preservation during debugging and testing. #4666 request, g, and other context-locals point to the correct data when running code in the interactive debugger console. #2836 Teardown functions are always run at the end of the request, even if the context is preserved. They are also run after the preserved context is popped. stream_with_context preserves context separately from a with client block. It will be cleaned up when response.get_data() or response.close() is called. Allow returning a list from a view function, to convert it to a JSON response like a dict is. #4672 When type checking, allow TypedDict to be returned from view functions. #4695 Remove the --eager-loading/--lazy-loading options from the flask run command. The app is always eager loaded the first time, then lazily loaded in the reloader. The reloader always prints errors immediately but continues serving. Remove the internal DispatchingApp middleware used by the previous implementation. #4715 Version 2.1.3¶ Released 2022-07-13 Inline some optional imports that are only used for certain CLI commands. #4606 Relax type annotation for after_request functions. #4600 instance_path for namespace packages uses the path closest to the imported submodule. #4610 Clearer error message when render_template and render_template_string are used outside an application context. #4693 Version 2.1.2¶ Released 2022-04-28 Fix type annotation for json.loads, it accepts str or bytes. #4519 The --cert and --key options on flask run can be given in either order. #4459 Version 2.1.1¶ Released on 2022-03-30 Set the minimum required version of importlib_metadata to 3.6.0, which is required on Python < 3.10. #4502 Version 2.1.0¶ Released 2022-03-28 Drop support for Python 3.6. #4335 Update Click dependency to >= 8.0. #4008 Remove previously deprecated code. #4337 The CLI does not pass script_info to app factory functions. config.from_json is replaced by config.from_file(name, load=json.load). json functions no longer take an encoding parameter. safe_join is removed, use werkzeug.utils.safe_join instead. total_seconds is removed, use timedelta.total_seconds instead. The same blueprint cannot be registered with the same name. Use name= when registering to specify a unique name. The test client’s as_tuple parameter is removed. Use response.request.environ instead. #4417 Some parameters in send_file and send_from_directory were renamed in 2.0. The deprecation period for the old names is extended to 2.2. Be sure to test with deprecation warnings visible. attachment_filename is renamed to download_name. cache_timeout is renamed to max_age. add_etags is renamed to etag. filename is renamed to path. The RequestContext.g property is deprecated. Use g directly or AppContext.g instead. #3898 copy_current_request_context can decorate async functions. #4303 The CLI uses importlib.metadata instead of pkg_resources to load command entry points. #4419 Overriding FlaskClient.open will not cause an error on redirect. #3396 Add an --exclude-patterns option to the flask run CLI command to specify patterns that will be ignored by the reloader. #4188 When using lazy loading (the default with the debugger), the Click context from the flask run command remains available in the loader thread. #4460 Deleting the session cookie uses the httponly flag. #4485 Relax typing for errorhandler to allow the user to use more precise types and decorate the same function multiple times. #4095, 4295, 4297 Fix typing for __exit__ methods for better compatibility with ExitStack. #4474 From Werkzeug, for redirect responses the Location header URL will remain relative, and exclude the scheme and domain, by default. #4496 Add Config.from_prefixed_env() to load config values from environment variables that start with FLASK_ or another prefix. This parses values as JSON by default, and allows setting keys in nested dicts. #4479 Version 2.0.3¶ Released 2022-02-14 The test client’s as_tuple parameter is deprecated and will be removed in Werkzeug 2.1. It is now also deprecated in Flask, to be removed in Flask 2.1, while remaining compatible with both in 2.0.x. Use response.request.environ instead. #4341 Fix type annotation for errorhandler decorator. #4295 Revert a change to the CLI that caused it to hide ImportError tracebacks when importing the application. #4307 app.json_encoder and json_decoder are only passed to dumps and loads if they have custom behavior. This improves performance, mainly on PyPy. #4349 Clearer error message when after_this_request is used outside a request context. #4333 Version 2.0.2¶ Released 2021-10-04 Fix type annotation for teardown_* methods. #4093 Fix type annotation for before_request and before_app_request decorators. #4104 Fixed the issue where typing requires template global decorators to accept functions with no arguments. #4098 Support View and MethodView instances with async handlers. #4112 Enhance typing of app.errorhandler decorator. #4095 Fix registering a blueprint twice with differing names. #4124 Fix the type of static_folder to accept pathlib.Path. #4150 jsonify handles decimal.Decimal by encoding to str. #4157 Correctly handle raising deferred errors in CLI lazy loading. #4096 The CLI loader handles **kwargs in a create_app function. #4170 Fix the order of before_request and other callbacks that trigger before the view returns. They are called from the app down to the closest nested blueprint. #4229 Version 2.0.1¶ Released 2021-05-21 Re-add the filename parameter in send_from_directory. The filename parameter has been renamed to path, the old name is deprecated. #4019 Mark top-level names as exported so type checking understands imports in user projects. #4024 Fix type annotation for g and inform mypy that it is a namespace object that has arbitrary attributes. #4020 Fix some types that weren’t available in Python 3.6.0. #4040 Improve typing for send_file, send_from_directory, and get_send_file_max_age. #4044, #4026 Show an error when a blueprint name contains a dot. The . has special meaning, it is used to separate (nested) blueprint names and the endpoint name. #4041 Combine URL prefixes when nesting blueprints that were created with a url_prefix value. #4037 Revert a change to the order that URL matching was done. The URL is again matched after the session is loaded, so the session is available in custom URL converters. #4053 Re-add deprecated Config.from_json, which was accidentally removed early. #4078 Improve typing for some functions using Callable in their type signatures, focusing on decorator factories. #4060 Nested blueprints are registered with their dotted name. This allows different blueprints with the same name to be nested at different locations. #4069 register_blueprint takes a name option to change the (pre-dotted) name the blueprint is registered with. This allows the same blueprint to be registered multiple times with unique names for url_for. Registering the same blueprint with the same name multiple times is deprecated. #1091 Improve typing for stream_with_context. #4052 Version 2.0.0¶ Released 2021-05-11 Drop support for Python 2 and 3.5. Bump minimum versions of other Pallets >= 2, Jinja2 >= 3, MarkupSafe >= 2, ItsDangerous >= 2, Click >= 8. Be sure to check the change logs for each project. For better compatibility with other applications (e.g. Celery) that still require Click 7, there is no hard dependency on Click 8 yet, but using Click 7 will trigger a DeprecationWarning and Flask 2.1 will depend on Click 8. JSON support no longer uses simplejson. To use another JSON module, override app.json_encoder and json_decoder. #3555 The encoding option to JSON functions is deprecated. #3562 Passing script_info to app factory functions is deprecated. This was not portable outside the flask command. Use click.get_current_context().obj if it’s needed. #3552 The CLI shows better error messages when the app failed to load when looking up commands. #2741 Add SessionInterface.get_cookie_name to allow setting the session cookie name dynamically. #3369 Add Config.from_file to load config using arbitrary file loaders, such as toml.load or json.load. Config.from_json is deprecated in favor of this. #3398 The flask run command will only defer errors on reload. Errors present during the initial call will cause the server to exit with the traceback immediately. #3431 send_file raises a ValueError when passed an io object in text mode. Previously, it would respond with 200 OK and an empty file. #3358 When using ad-hoc certificates, check for the cryptography library instead of PyOpenSSL. #3492 When specifying a factory function with FLASK_APP, keyword argument can be passed. #3553 When loading a .env or .flaskenv file, the current working directory is no longer changed to the location of the file. #3560 When returning a (response, headers) tuple from a view, the headers replace rather than extend existing headers on the response. For example, this allows setting the Content-Type for jsonify(). Use response.headers.extend() if extending is desired. #3628 The Scaffold class provides a common API for the Flask and Blueprint classes. Blueprint information is stored in attributes just like Flask, rather than opaque lambda functions. This is intended to improve consistency and maintainability. #3215 Include samesite and secure options when removing the session cookie. #3726 Support passing a pathlib.Path to static_folder. #3579 send_file and send_from_directory are wrappers around the implementations in werkzeug.utils. #3828 Some send_file parameters have been renamed, the old names are deprecated. attachment_filename is renamed to download_name. cache_timeout is renamed to max_age. add_etags is renamed to etag. #3828, 3883 send_file passes download_name even if as_attachment=False by using #3828 send_file sets conditional=True and max_age=None by default. Cache-Control is set to no-cache if max_age is not set, otherwise public. This tells browsers to validate conditional requests instead of using a timed cache. #3828 helpers.safe_join is deprecated. Use werkzeug.utils.safe_join instead. #3828 The request context does route matching before opening the session. This could allow a session interface to change behavior based on request.endpoint. #3776 Use Jinja’s implementation of the |tojson filter. #3881 Add route decorators for common HTTP methods. For example, @app.post(\"/login\") is a shortcut for @app.route(\"/login\", methods=[\"POST\"]). #3907 Support async views, error handlers, before and after request, and teardown functions. #3412 Support nesting blueprints. #593, 1548, #3923 Set the default encoding to “UTF-8” when loading .env and .flaskenv files to allow to use non-ASCII characters. #3931 flask shell sets up tab and history completion like the default python shell if readline is installed. #3941 helpers.total_seconds() is deprecated. Use timedelta.total_seconds() instead. #3962 Add type hinting. #3973. Version 1.1.4¶ Released 2021-05-13 Update static_folder to use _compat.fspath instead of os.fspath to continue supporting Python < 3.6 #4050 Version 1.1.3¶ Released 2021-05-13 Set maximum versions of Werkzeug, Jinja, Click, and ItsDangerous. #4043 Re-add support for passing a pathlib.Path for static_folder. #3579 Version 1.1.2¶ Released 2020-04-03 Work around an issue when running the flask command with an external debugger on Windows. #3297 The static route will not catch all URLs if the Flask static_folder argument ends with a slash. #3452 Version 1.1.1¶ Released 2019-07-08 The flask.json_available flag was added back for compatibility with some extensions. It will raise a deprecation warning when used, and will be removed in version 2.0.0. #3288 Version 1.1.0¶ Released 2019-07-04 Bump minimum Werkzeug version to >= 0.15. Drop support for Python 3.4. Error handlers for InternalServerError or 500 will always be passed an instance of InternalServerError. If they are invoked due to an unhandled exception, that original exception is now available as e.original_exception rather than being passed directly to the handler. The same is true if the handler is for the base HTTPException. This makes error handler behavior more consistent. #3266 Flask.finalize_request is called for all unhandled exceptions even if there is no 500 error handler. Flask.logger takes the same name as Flask.name (the value passed as Flask(import_name). This reverts 1.0’s behavior of always logging to \"flask.app\", in order to support multiple apps in the same process. A warning will be shown if old configuration is detected that needs to be moved. #2866 RequestContext.copy includes the current session object in the request context copy. This prevents session pointing to an out-of-date object. #2935 Using built-in RequestContext, unprintable Unicode characters in Host header will result in a HTTP 400 response and not HTTP 500 as previously. #2994 send_file supports PathLike objects as described in PEP 519, to support pathlib in Python 3. #3059 send_file supports BytesIO partial content. #2957 open_resource accepts the “rt” file mode. This still does the same thing as “r”. #3163 The MethodView.methods attribute set in a base class is used by subclasses. #3138 Flask.jinja_options is a dict instead of an ImmutableDict to allow easier configuration. Changes must still be made before creating the environment. #3190 Flask’s JSONMixin for the request and response wrappers was moved into Werkzeug. Use Werkzeug’s version with Flask-specific support. This bumps the Werkzeug dependency to >= 0.15. #3125 The flask command entry point is simplified to take advantage of Werkzeug 0.15’s better reloader support. This bumps the Werkzeug dependency to >= 0.15. #3022 Support static_url_path that ends with a forward slash. #3134 Support empty static_folder without requiring setting an empty static_url_path as well. #3124 jsonify supports dataclass objects. #3195 Allow customizing the Flask.url_map_class used for routing. #3069 The development server port can be set to 0, which tells the OS to pick an available port. #2926 The return value from cli.load_dotenv is more consistent with the documentation. It will return False if python-dotenv is not installed, or if the given path isn’t a file. #2937 Signaling support has a stub for the connect_via method when the Blinker library is not installed. #3208 Add an --extra-files option to the flask run CLI command to specify extra files that will trigger the reloader on change. #2897 Allow returning a dictionary from a view function. Similar to how returning a string will produce a text/html response, returning a dict will call jsonify to produce a application/json response. #3111 Blueprints have a cli Click group like app.cli. CLI commands registered with a blueprint will be available as a group under the flask command. #1357. When using the test client as a context manager (with client:), all preserved request contexts are popped when the block exits, ensuring nested contexts are cleaned up correctly. #3157 Show a better error message when the view return type is not supported. #3214 flask.testing.make_test_environ_builder() has been deprecated in favour of a new class flask.testing.EnvironBuilder. #3232 The flask run command no longer fails if Python is not built with SSL support. Using the --cert option will show an appropriate error message. #3211 URL matching now occurs after the request context is pushed, rather than when it’s created. This allows custom URL converters to access the app and request contexts, such as to query a database for an id. #3088 Version 1.0.4¶ Released 2019-07-04 The key information for BadRequestKeyError is no longer cleared outside debug mode, so error handlers can still access it. This requires upgrading to Werkzeug 0.15.5. #3249 send_file url quotes the “:” and “/” characters for more compatible UTF-8 filename support in some browsers. #3074 Fixes for PEP 451 import loaders and pytest 5.x. #3275 Show message about dotenv on stderr instead of stdout. #3285 Version 1.0.3¶ Released 2019-05-17 send_file encodes filenames as ASCII instead of Latin-1 (ISO-8859-1). This fixes compatibility with Gunicorn, which is stricter about header encodings than PEP 3333. #2766 Allow custom CLIs using FlaskGroup to set the debug flag without it always being overwritten based on environment variables. #2765 flask --version outputs Werkzeug’s version and simplifies the Python version. #2825 send_file handles an attachment_filename that is a native Python 2 string (bytes) with UTF-8 coded bytes. #2933 A catch-all error handler registered for HTTPException will not handle RoutingException, which is used internally during routing. This fixes the unexpected behavior that had been introduced in 1.0. #2986 Passing the json argument to app.test_client does not push/pop an extra app context. #2900 Version 1.0.2¶ Released 2018-05-02 Fix more backwards compatibility issues with merging slashes between a blueprint prefix and route. #2748 Fix error with flask routes command when there are no routes. #2751 Version 1.0.1¶ Released 2018-04-29 Fix registering partials (with no __name__) as view functions. #2730 Don’t treat lists returned from view functions the same as tuples. Only tuples are interpreted as response data. #2736 Extra slashes between a blueprint’s url_prefix and a route URL are merged. This fixes some backwards compatibility issues with the change in 1.0. #2731, #2742 Only trap BadRequestKeyError errors in debug mode, not all BadRequest errors. This allows abort(400) to continue working as expected. #2735 The FLASK_SKIP_DOTENV environment variable can be set to 1 to skip automatically loading dotenv files. #2722 Version 1.0¶ Released 2018-04-26 Python 2.6 and 3.3 are no longer supported. Bump minimum dependency versions to the latest stable >= 0.14, Jinja >= 2.10, itsdangerous >= 0.24, Click >= 5.1. #2586 Skip app.run when a Flask application is run from the command line. This avoids some behavior that was confusing to debug. Change the default for JSONIFY_PRETTYPRINT_REGULAR to False. ~json.jsonify returns a compact format by default, and an indented format in debug mode. #2193 Flask.__init__ accepts the host_matching argument and sets it on Flask.url_map. #1559 Flask.__init__ accepts the static_host argument and passes it as the host argument when defining the static route. #1559 send_file supports Unicode in attachment_filename. #2223 Pass _scheme argument from url_for to Flask.handle_url_build_error. #2017 Flask.add_url_rule accepts the provide_automatic_options argument to disable adding the OPTIONS method. #1489 MethodView subclasses inherit method handlers from base classes. #1936 Errors caused while opening the session at the beginning of the request are handled by the app’s error handlers. #2254 Blueprints gained Blueprint.json_encoder and Blueprint.json_decoder attributes to override the app’s encoder and decoder. #1898 Flask.make_response raises TypeError instead of ValueError for bad response types. The error messages have been improved to describe why the type is invalid. #2256 Add routes CLI command to output routes registered on the application. #2259 Show warning when session cookie domain is a bare hostname or an IP address, as these may not behave properly in some browsers, such as Chrome. #2282 Allow IP address as exact session cookie domain. #2282 SESSION_COOKIE_DOMAIN is set if it is detected through SERVER_NAME. #2282 Auto-detect zero-argument app factory called create_app or make_app from FLASK_APP. #2297 Factory functions are not required to take a script_info parameter to work with the flask command. If they take a single parameter or a parameter named script_info, the ScriptInfo object will be passed. #2319 FLASK_APP can be set to an app factory, with arguments if needed, for example FLASK_APP=myproject.app:create_app('dev'). #2326 FLASK_APP can point to local packages that are not installed in editable mode, although pip install -e is still preferred. #2414 The View class attribute View.provide_automatic_options is set in View.as_view, to be detected by Flask.add_url_rule. #2316 Error handling will try handlers registered for blueprint, code, app, code, blueprint, exception, app, exception. #2314 Cookie is added to the response’s Vary header if the session is accessed at all during the request (and not deleted). #2288 Flask.test_request_context accepts subdomain and url_scheme arguments for use when building the base URL. #1621 Set APPLICATION_ROOT to '/' by default. This was already the implicit default when it was set to None. TRAP_BAD_REQUEST_ERRORS is enabled by default in debug mode. BadRequestKeyError has a message with the bad key in debug mode instead of the generic bad request message. #2348 Allow registering new tags with TaggedJSONSerializer to support storing other types in the session cookie. #2352 Only open the session if the request has not been pushed onto the context stack yet. This allows stream_with_context generators to access the same session that the containing view uses. #2354 Add json keyword argument for the test client request methods. This will dump the given object as JSON and set the appropriate content type. #2358 Extract JSON handling to a mixin applied to both the Request and Response classes. This adds the Response.is_json and Response.get_json methods to the response to make testing JSON response much easier. #2358 Removed error handler caching because it caused unexpected results for some exception inheritance hierarchies. Register handlers explicitly for each exception if you want to avoid traversing the MRO. #2362 Fix incorrect JSON encoding of aware, non-UTC datetimes. #2374 Template auto reloading will honor debug mode even if Flask.jinja_env was already accessed. #2373 The following old deprecated code was removed. #2385 flask.ext - import extensions directly by their name instead of through the flask.ext namespace. For example, import flask.ext.sqlalchemy becomes import flask_sqlalchemy. Flask.init_jinja_globals - extend Flask.create_jinja_environment instead. Flask.error_handlers - tracked by Flask.error_handler_spec, use Flask.errorhandler to register handlers. Flask.request_globals_class - use Flask.app_ctx_globals_class instead. Flask.static_path - use Flask.static_url_path instead. Request.module - use Request.blueprint instead. The Request.json property is no longer deprecated. #1421 Support passing a EnvironBuilder or dict to test_client.open. #2412 The flask command and Flask.run will load environment variables from .env and .flaskenv files if python-dotenv is installed. #2416 When passing a full URL to the test client, the scheme in the URL is used instead of PREFERRED_URL_SCHEME. #2430 Flask.logger has been simplified. LOGGER_NAME and LOGGER_HANDLER_POLICY config was removed. The logger is always named flask.app. The level is only set on first access, it doesn’t check Flask.debug each time. Only one format is used, not different ones depending on Flask.debug. No handlers are removed, and a handler is only added if no handlers are already configured. #2436 Blueprint view function names may not contain dots. #2450 Fix a ValueError caused by invalid Range requests in some cases. #2526 The development server uses threads by default. #2529 Loading config files with silent=True will ignore ENOTDIR errors. #2581 Pass --cert and --key options to flask run to run the development server over HTTPS. #2606 Added SESSION_COOKIE_SAMESITE to control the SameSite attribute on the session cookie. #2607 Added Flask.test_cli_runner to create a Click runner that can invoke Flask CLI commands for testing. #2636 Subdomain matching is disabled by default and setting SERVER_NAME does not implicitly enable it. It can be enabled by passing subdomain_matching=True to the Flask constructor. #2635 A single trailing slash is stripped from the blueprint url_prefix when it is registered with the app. #2629 Request.get_json doesn’t cache the result if parsing fails when silent is true. #2651 Request.get_json no longer accepts arbitrary encodings. Incoming JSON should be encoded using UTF-8 per RFC 8259, but Flask will autodetect UTF-8, -16, or -32. #2691 Added MAX_COOKIE_SIZE and Response.max_cookie_size to control when Werkzeug warns about large cookies that browsers may ignore. #2693 Updated documentation theme to make docs look better in small windows. #2709 Rewrote the tutorial docs and example project to take a more structured approach to help new users avoid common pitfalls. #2676 Version 0.12.5¶ Released 2020-02-10 Pin Werkzeug to < 1.0.0. #3497 Version 0.12.4¶ Released 2018-04-29 Repackage 0.12.3 to fix package layout issue. #2728 Version 0.12.3¶ Released 2018-04-26 Request.get_json no longer accepts arbitrary encodings. Incoming JSON should be encoded using UTF-8 per RFC 8259, but Flask will autodetect UTF-8, -16, or -32. #2692 Fix a Python warning about imports when using python -m flask. #2666 Fix a ValueError caused by invalid Range requests in some cases. Version 0.12.2¶ Released 2017-05-16 Fix a bug in safe_join on Windows. Version 0.12.1¶ Released 2017-03-31 Prevent flask run from showing a NoAppException when an ImportError occurs within the imported application module. Fix encoding behavior of app.config.from_pyfile for Python 3. #2118 Use the SERVER_NAME config if it is present as default values for app.run. #2109, #2152 Call ctx.auto_pop with the exception object instead of None, in the event that a BaseException such as KeyboardInterrupt is raised in a request handler. Version 0.12¶ Released 2016-12-21, codename Punsch The cli command now responds to --version. Mimetype guessing and ETag generation for file-like objects in send_file has been removed. #104, :pr`1849` Mimetype guessing in send_file now fails loudly and doesn’t fall back to application/octet-stream. #1988 Make flask.safe_join able to join multiple paths like os.path.join #1730 Revert a behavior change that made the dev server crash instead of returning an Internal Server Error. #2006 Correctly invoke response handlers for both regular request dispatching as well as error handlers. Disable logger propagation by default for the app logger. Add support for range requests in send_file. app.test_client includes preset default environment, which can now be directly set, instead of per client.get. Fix crash when running under PyPy3. #1814 Version 0.11.1¶ Released 2016-06-07 Fixed a bug that prevented FLASK_APP=foobar/__init__.py from working. #1872 Version 0.11¶ Released 2016-05-29, codename Absinthe Added support to serializing top-level arrays to jsonify. This introduces a security risk in ancient browsers. Added before_render_template signal. Added **kwargs to Flask.test_client to support passing additional keyword arguments to the constructor of Flask.test_client_class. Added SESSION_REFRESH_EACH_REQUEST config key that controls the set-cookie behavior. If set to True a permanent session will be refreshed each request and get their lifetime extended, if set to False it will only be modified if the session actually modifies. Non permanent sessions are not affected by this and will always expire if the browser window closes. Made Flask support custom JSON mimetypes for incoming data. Added support for returning tuples in the form (response, headers) from a view function. Added Config.from_json. Added Flask.config_class. Added Config.get_namespace. Templates are no longer automatically reloaded outside of debug mode. This can be configured with the new TEMPLATES_AUTO_RELOAD config key. Added a workaround for a limitation in Python 3.3’s namespace loader. Added support for explicit root paths when using Python 3.3’s namespace packages. Added flask and the flask.cli module to start the local debug server through the click CLI system. This is recommended over the old flask.run() method as it works faster and more reliable due to a different design and also replaces Flask-Script. Error handlers that match specific classes are now checked first, thereby allowing catching exceptions that are subclasses of HTTP exceptions (in werkzeug.exceptions). This makes it possible for an extension author to create exceptions that will by default result in the HTTP error of their choosing, but may be caught with a custom error handler if desired. Added Config.from_mapping. Flask will now log by default even if debug is disabled. The log format is now hardcoded but the default log handling can be disabled through the LOGGER_HANDLER_POLICY configuration key. Removed deprecated module functionality. Added the EXPLAIN_TEMPLATE_LOADING config flag which when enabled will instruct Flask to explain how it locates templates. This should help users debug when the wrong templates are loaded. Enforce blueprint handling in the order they were registered for template loading. Ported test suite to py.test. Deprecated request.json in favour of request.get_json(). Add “pretty” and “compressed” separators definitions in jsonify() method. Reduces JSON response size when JSONIFY_PRETTYPRINT_REGULAR=False by removing unnecessary white space included by default after separators. JSON responses are now terminated with a newline character, because it is a convention that UNIX text files end with a newline and some clients don’t deal well when this newline is missing. #1262 The automatically provided OPTIONS method is now correctly disabled if the user registered an overriding rule with the lowercase-version options. #1288 flask.json.jsonify now supports the datetime.date type. #1326 Don’t leak exception info of already caught exceptions to context teardown handlers. #1393 Allow custom Jinja environment subclasses. #1422 Updated extension dev guidelines. flask.g now has pop() and setdefault methods. Turn on autoescape for flask.templating.render_template_string by default. #1515 flask.ext is now deprecated. #1484 send_from_directory now raises BadRequest if the filename is invalid on the server OS. #1763 Added the JSONIFY_MIMETYPE configuration variable. #1728 Exceptions during teardown handling will no longer leave bad application contexts lingering around. Fixed broken test_appcontext_signals() test case. Raise an AttributeError in helpers.find_package with a useful message explaining why it is raised when a PEP 302 import hook is used without an is_package() method. Fixed an issue causing exceptions raised before entering a request or app context to be passed to teardown handlers. Fixed an issue with query parameters getting removed from requests in the test client when absolute URLs were requested. Made @before_first_request into a decorator as intended. Fixed an etags bug when sending a file streams with a name. Fixed send_from_directory not expanding to the application root path correctly. Changed logic of before first request handlers to flip the flag after invoking. This will allow some uses that are potentially dangerous but should probably be permitted. Fixed Python 3 bug when a handler from app.url_build_error_handlers reraises the BuildError. Version 0.10.1¶ Released 2013-06-14 Fixed an issue where |tojson was not quoting single quotes which made the filter not work properly in HTML attributes. Now it’s possible to use that filter in single quoted attributes. This should make using that filter with angular.js easier. Added support for byte strings back to the session system. This broke compatibility with the common case of people putting binary data for token verification into the session. Fixed an issue where registering the same method twice for the same endpoint would trigger an exception incorrectly. Version 0.10¶ Released 2013-06-13, codename Limoncello Changed default cookie serialization format from pickle to JSON to limit the impact an attacker can do if the secret key leaks. Added template_test methods in addition to the already existing template_filter method family. Added template_global methods in addition to the already existing template_filter method family. Set the content-length header for x-sendfile. tojson filter now does not escape script blocks in HTML5 parsers. tojson used in templates is now safe by default. This was allowed due to the different escaping behavior. Flask will now raise an error if you attempt to register a new function on an already used endpoint. Added wrapper module around simplejson and added default serialization of datetime objects. This allows much easier customization of how JSON is handled by Flask or any Flask extension. Removed deprecated internal flask.session module alias. Use flask.sessions instead to get the session module. This is not to be confused with flask.session the session proxy. Templates can now be rendered without request context. The behavior is slightly different as the request, session and g objects will not be available and blueprint’s context processors are not called. The config object is now available to the template as a real global and not through a context processor which makes it available even in imported templates by default. Added an option to generate non-ascii encoded JSON which should result in less bytes being transmitted over the network. It’s disabled by default to not cause confusion with existing libraries that might expect flask.json.dumps to return bytes by default. flask.g is now stored on the app context instead of the request context. flask.g now gained a get() method for not erroring out on non existing items. flask.g now can be used with the in operator to see what’s defined and it now is iterable and will yield all attributes stored. flask.Flask.request_globals_class got renamed to flask.Flask.app_ctx_globals_class which is a better name to what it does since 0.10. request, session and g are now also added as proxies to the template context which makes them available in imported templates. One has to be very careful with those though because usage outside of macros might cause caching. Flask will no longer invoke the wrong error handlers if a proxy exception is passed through. Added a workaround for chrome’s cookies in localhost not working as intended with domain names. Changed logic for picking defaults for cookie values from sessions to work better with Google Chrome. Added message_flashed signal that simplifies flashing testing. Added support for copying of request contexts for better working with greenlets. Removed custom JSON HTTP exception subclasses. If you were relying on them you can reintroduce them again yourself trivially. Using them however is strongly discouraged as the interface was flawed. Python requirements Python 2.6 or 2.7 now to prepare for Python 3.3 port. Changed how the teardown system is informed about exceptions. This is now more reliable in case something handles an exception halfway through the error handling process. Request context preservation in debug mode now keeps the exception information around which means that teardown handlers are able to distinguish error from success cases. Added the JSONIFY_PRETTYPRINT_REGULAR configuration variable. Flask now orders JSON keys by default to not trash HTTP caches due to different hash seeds between different workers. Added appcontext_pushed and appcontext_popped signals. The builtin run method now takes the SERVER_NAME into account when picking the default port to run on. Added flask.request.get_json() as a replacement for the old flask.request.json property. Version 0.9¶ Released 2012-07-01, codename Campari The Request.on_json_loading_failed now returns a JSON formatted response by default. The url_for function now can generate anchors to the generated links. The url_for function now can also explicitly generate URL rules specific to a given HTTP method. Logger now only returns the debug log setting if it was not set explicitly. Unregister a circular dependency between the WSGI environment and the request object when shutting down the request. This means that environ werkzeug.request will be None after the response was returned to the WSGI server but has the advantage that the garbage collector is not needed on CPython to tear down the request unless the user created circular dependencies themselves. Session is now stored after callbacks so that if the session payload is stored in the session you can still modify it in an after request callback. The Flask class will avoid importing the provided import name if it can (the required first parameter), to benefit tools which build Flask instances programmatically. The Flask class will fall back to using import on systems with custom module hooks, e.g. Google App Engine, or when the import name is inside a zip archive (usually an egg) prior to Python 2.7. Blueprints now have a decorator to add custom template filters application wide, Blueprint.app_template_filter. The Flask and Blueprint classes now have a non-decorator method for adding custom template filters application wide, Flask.add_template_filter and Blueprint.add_app_template_filter. The get_flashed_messages function now allows rendering flashed message categories in separate blocks, through a category_filter argument. The Flask.run method now accepts None for host and port arguments, using default values when None. This allows for calling run using configuration values, e.g. app.run(app.config.get('MYHOST'), app.config.get('MYPORT')), with proper behavior whether or not a config file is provided. The render_template method now accepts a either an iterable of template names or a single template name. Previously, it only accepted a single template name. On an iterable, the first template found is rendered. Added Flask.app_context which works very similar to the request context but only provides access to the current application. This also adds support for URL generation without an active request context. View functions can now return a tuple with the first instance being an instance of Response. This allows for returning jsonify(error=\"error msg\"), 400 from a view function. Flask and Blueprint now provide a get_send_file_max_age hook for subclasses to override behavior of serving static files from Flask when using Flask.send_static_file (used for the default static file handler) and helpers.send_file. This hook is provided a filename, which for example allows changing cache controls by file extension. The default max-age for send_file and static files can be configured through a new SEND_FILE_MAX_AGE_DEFAULT configuration variable, which is used in the default get_send_file_max_age implementation. Fixed an assumption in sessions implementation which could break message flashing on sessions implementations which use external storage. Changed the behavior of tuple return values from functions. They are no longer arguments to the response object, they now have a defined meaning. Added Flask.request_globals_class to allow a specific class to be used on creation of the g instance of each request. Added required_methods attribute to view functions to force-add methods on registration. Added flask.after_this_request. Added flask.stream_with_context and the ability to push contexts multiple times without producing unexpected behavior. Version 0.8.1¶ Released 2012-07-01 Fixed an issue with the undocumented flask.session module to not work properly on Python 2.5. It should not be used but did cause some problems for package managers. Version 0.8¶ Released 2011-09-29, codename Rakija Refactored session support into a session interface so that the implementation of the sessions can be changed without having to override the Flask class. Empty session cookies are now deleted properly automatically. View functions can now opt out of getting the automatic OPTIONS implementation. HTTP exceptions and Bad Request errors can now be trapped so that they show up normally in the traceback. Flask in debug mode is now detecting some common problems and tries to warn you about them. Flask in debug mode will now complain with an assertion error if a view was attached after the first request was handled. This gives earlier feedback when users forget to import view code ahead of time. Added the ability to register callbacks that are only triggered once at the beginning of the first request with Flask.before_first_request. Malformed JSON data will now trigger a bad request HTTP exception instead of a value error which usually would result in a 500 internal server error if not handled. This is a backwards incompatible change. Applications now not only have a root path where the resources and modules are located but also an instance path which is the designated place to drop files that are modified at runtime (uploads etc.). Also this is conceptually only instance depending and outside version control so it’s the perfect place to put configuration files etc. Added the APPLICATION_ROOT configuration variable. Implemented TestClient.session_transaction to easily modify sessions from the test environment. Refactored test client internally. The APPLICATION_ROOT configuration variable as well as SERVER_NAME are now properly used by the test client as defaults. Added View.decorators to support simpler decorating of pluggable (class-based) views. Fixed an issue where the test client if used with the “with” statement did not trigger the execution of the teardown handlers. Added finer control over the session cookie parameters. HEAD requests to a method view now automatically dispatch to the get method if no handler was implemented. Implemented the virtual flask.ext package to import extensions from. The context preservation on exceptions is now an integral component of Flask itself and no longer of the test client. This cleaned up some internal logic and lowers the odds of runaway request contexts in unittests. Fixed the Jinja environment’s list_templates method not returning the correct names when blueprints or modules were involved. Version 0.7.2¶ Released 2011-07-06 Fixed an issue with URL processors not properly working on blueprints. Version 0.7.1¶ Released 2011-06-29 Added missing future import that broke 2.5 compatibility. Fixed an infinite redirect issue with blueprints. Version 0.7¶ Released 2011-06-28, codename Grappa Added Flask.make_default_options_response which can be used by subclasses to alter the default behavior for OPTIONS responses. Unbound locals now raise a proper RuntimeError instead of an AttributeError. Mimetype guessing and etag support based on file objects is now deprecated for send_file because it was unreliable. Pass filenames instead or attach your own etags and provide a proper mimetype by hand. Static file handling for modules now requires the name of the static folder to be supplied explicitly. The previous autodetection was not reliable and caused issues on Google’s App Engine. Until 1.0 the old behavior will continue to work but issue dependency warnings. Fixed a problem for Flask to run on jython. Added a PROPAGATE_EXCEPTIONS configuration variable that can be used to flip the setting of exception propagation which previously was linked to DEBUG alone and is now linked to either DEBUG or TESTING. Flask no longer internally depends on rules being added through the add_url_rule function and can now also accept regular werkzeug rules added to the url map. Added an endpoint method to the flask application object which allows one to register a callback to an arbitrary endpoint with a decorator. Use Last-Modified for static file sending instead of Date which was incorrectly introduced in 0.6. Added create_jinja_loader to override the loader creation process. Implemented a silent flag for config.from_pyfile. Added teardown_request decorator, for functions that should run at the end of a request regardless of whether an exception occurred. Also the behavior for after_request was changed. It’s now no longer executed when an exception is raised. Implemented has_request_context. Deprecated init_jinja_globals. Override the Flask.create_jinja_environment method instead to achieve the same functionality. Added safe_join. The automatic JSON request data unpacking now looks at the charset mimetype parameter. Don’t modify the session on get_flashed_messages if there are no messages in the session. before_request handlers are now able to abort requests with errors. It is not possible to define user exception handlers. That way you can provide custom error messages from a central hub for certain errors that might occur during request processing (for instance database connection errors, timeouts from remote resources etc.). Blueprints can provide blueprint specific error handlers. Implemented generic class-based views. Version 0.6.1¶ Released 2010-12-31 Fixed an issue where the default OPTIONS response was not exposing all valid methods in the Allow header. Jinja template loading syntax now allows “./” in front of a template load path. Previously this caused issues with module setups. Fixed an issue where the subdomain setting for modules was ignored for the static folder. Fixed a security problem that allowed clients to download arbitrary files if the host server was a windows based operating system and the client uses backslashes to escape the directory the files where exposed from. Version 0.6¶ Released 2010-07-27, codename Whisky After request functions are now called in reverse order of registration. OPTIONS is now automatically implemented by Flask unless the application explicitly adds ‘OPTIONS’ as method to the URL rule. In this case no automatic OPTIONS handling kicks in. Static rules are now even in place if there is no static folder for the module. This was implemented to aid GAE which will remove the static folder if it’s part of a mapping in the .yml file. Flask.config is now available in the templates as config. Context processors will no longer override values passed directly to the render function. Added the ability to limit the incoming request data with the new MAX_CONTENT_LENGTH configuration value. The endpoint for the Module.add_url_rule method is now optional to be consistent with the function of the same name on the application object. Added a make_response function that simplifies creating response object instances in views. Added signalling support based on blinker. This feature is currently optional and supposed to be used by extensions and applications. If you want to use it, make sure to have blinker installed. Refactored the way URL adapters are created. This process is now fully customizable with the Flask.create_url_adapter method. Modules can now register for a subdomain instead of just an URL prefix. This makes it possible to bind a whole module to a configurable subdomain. Version 0.5.2¶ Released 2010-07-15 Fixed another issue with loading templates from directories when modules were used. Version 0.5.1¶ Released 2010-07-06 Fixes an issue with template loading from directories when modules where used. Version 0.5¶ Released 2010-07-06, codename Calvados Fixed a bug with subdomains that was caused by the inability to specify the server name. The server name can now be set with the SERVER_NAME config key. This key is now also used to set the session cookie cross-subdomain wide. Autoescaping is no longer active for all templates. Instead it is only active for .html, .htm, .xml and .xhtml. Inside templates this behavior can be changed with the autoescape tag. Refactored Flask internally. It now consists of more than a single file. send_file now emits etags and has the ability to do conditional responses builtin. (temporarily) dropped support for zipped applications. This was a rarely used feature and led to some confusing behavior. Added support for per-package template and static-file directories. Removed support for create_jinja_loader which is no longer used in 0.5 due to the improved module support. Added a helper function to expose files from any directory. Version 0.4¶ Released 2010-06-18, codename Rakia Added the ability to register application wide error handlers from modules. Flask.after_request handlers are now also invoked if the request dies with an exception and an error handling page kicks in. Test client has not the ability to preserve the request context for a little longer. This can also be used to trigger custom requests that do not pop the request stack for testing. Because the Python standard library caches loggers, the name of the logger is configurable now to better support unittests. Added TESTING switch that can activate unit testing helpers. The logger switches to DEBUG mode now if debug is enabled. Version 0.3.1¶ Released 2010-05-28 Fixed a error reporting bug with Config.from_envvar. Removed some unused code. Release does no longer include development leftover files (.git folder for themes, built documentation in zip and pdf file and some .pyc files) Version 0.3¶ Released 2010-05-28, codename Schnaps Added support for categories for flashed messages. The application now configures a logging.Handler and will log request handling exceptions to that logger when not in debug mode. This makes it possible to receive mails on server errors for example. Added support for context binding that does not require the use of the with statement for playing in the console. The request context is now available within the with statement making it possible to further push the request context or pop it. Added support for configurations. Version 0.2¶ Released 2010-05-12, codename Jägermeister Various bugfixes Integrated JSON support Added get_template_attribute helper function. Flask.add_url_rule can now also register a view function. Refactored internal request dispatching. Server listens on 127.0.0.1 by default now to fix issues with chrome. Added external URL support. Added support for send_file. Module support and internal request handling refactoring to better support pluggable applications. Sessions can be set to be permanent now on a per-session basis. Better error reporting on missing secret keys. Added support for Google Appengine. Version 0.1¶ Released 2010-04-16 First public preview release. Contents Changes Version 3.1.3 Version 3.1.2 Version 3.1.1 Version 3.1.0 Version 3.0.3 Version 3.0.2 Version 3.0.1 Version 3.0.0 Version 2.3.3 Version 2.3.2 Version 2.3.1 Version 2.3.0 Version 2.2.5 Version 2.2.4 Version 2.2.3 Version 2.2.2 Version 2.2.1 Version 2.2.0 Version 2.1.3 Version 2.1.2 Version 2.1.1 Version 2.1.0 Version 2.0.3 Version 2.0.2 Version 2.0.1 Version 2.0.0 Version 1.1.4 Version 1.1.3 Version 1.1.2 Version 1.1.1 Version 1.1.0 Version 1.0.4 Version 1.0.3 Version 1.0.2 Version 1.0.1 Version 1.0 Version 0.12.5 Version 0.12.4 Version 0.12.3 Version 0.12.2 Version 0.12.1 Version 0.12 Version 0.11.1 Version 0.11 Version 0.10.1 Version 0.10 Version 0.9 Version 0.8.1 Version 0.8 Version 0.7.2 Version 0.7.1 Version 0.7 Version 0.6.1 Version 0.6 Version 0.5.2 Version 0.5.1 Version 0.5 Version 0.4 Version 0.3.1 Version 0.3 Version 0.2 Version 0.1 Navigation Overview License Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.810Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":15424}}16{"id":"doc-python_module_index_flask_documentation_3_1_x-2afdb58e","source":"documentation","title":"Python Module Index — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/py-modindex/","text":"Python Module Index f f flask flask.json flask.json.tag Navigation Overview Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.986Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":26}}17{"id":"doc-installation_flask_documentation_3_1_x-45491d96","source":"documentation","title":"Installation — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/installation/","text":"Installation¶ Python Version¶ We recommend using the latest version of Python. Flask supports Python 3.9 and newer. Dependencies¶ These distributions will be installed automatically when installing Flask. Werkzeug implements WSGI, the standard Python interface between applications and servers. Jinja is a template language that renders the pages your application serves. MarkupSafe comes with Jinja. It escapes untrusted input when rendering templates to avoid injection attacks. ItsDangerous securely signs data to ensure its integrity. This is used to protect Flask’s session cookie. Click is a framework for writing command line applications. It provides the flask command and allows adding custom management commands. Blinker provides support for Signals. Optional dependencies¶ These distributions will not be installed automatically. Flask will detect and use them if you install them. python-dotenv enables support for Environment Variables From dotenv when running flask commands. Watchdog provides a faster, more efficient reloader for the development server. greenlet¶ You may choose to use Async with Gevent with your application. In this case, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is required. These are not minimum supported versions, they only indicate the first versions that added necessary features. You should use the latest versions of each. Virtual environments¶ Use a virtual environment to manage the dependencies for your project, both in development and in production. What problem does a virtual environment solve? The more Python projects you have, the more likely it is that you need to work with different versions of Python libraries, or even Python itself. Newer versions of libraries for one project can break compatibility in another project. Virtual environments are independent groups of Python libraries, one for each project. Packages installed for one project will not affect other projects or the operating system’s packages. Python comes bundled with the venv module to create virtual environments. Create an environment¶ Create a project folder and a .venv folder /LinuxWindows$ mkdir myproject $ cd myproject $ python3 -m venv .venv > mkdir myproject > cd myproject > py -3 -m venv .venv Activate the environment¶ Before you work on your project, activate the corresponding /LinuxWindows$ . .venv/bin/activate > .venv\\Scripts\\activate Your shell prompt will change to show the name of the activated environment. Install Flask¶ Within the activated environment, use the following command to install Flask: $ pip install Flask Flask is now installed. Check out the Quickstart or go to the Documentation Overview. Contents Installation Python Version Dependencies Optional dependencies greenlet Virtual environments Create an environment Activate the environment Install Flask Navigation Overview to Flask Quick search\n\nExample:\n```text\n$ mkdir myproject\n$ cd myproject\n$ python3 -m venv .venv\n```\n\nExample:\n```text\n> mkdir myproject\n> cd myproject\n> py -3 -m venv .venv\n```\n\nExample:\n```text\n$ . .venv/bin/activate\n```\n\nExample:\n```text\n> .venv\\Scripts\\activate\n```\n\nExample:\n```text\n$ pip install Flask\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.987Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":5,"totalLines":32,"estimatedTokens":795}}18{"id":"doc-welcome_to_flask_flask_documentation_3_1_x-26bd9ac7","source":"documentation","title":"Welcome to Flask — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/","text":"Welcome to Flask¶ Welcome to Flask’s documentation. Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications. Get started with Installation and then get an overview with the Quickstart. There is also a more detailed Tutorial that shows how to create a small but complete application with Flask. Common patterns are described in the Patterns for Flask section. The rest of the docs describe each component of Flask in detail, with a full reference in the API section. Flask depends on the Werkzeug WSGI toolkit, the Jinja template engine, and the Click CLI toolkit. Be sure to check their documentation as well as Flask’s when looking for information. User’s Guide¶ Flask provides configuration and conventions, with sensible defaults, to get started. This section of the documentation explains the different parts of the Flask framework and how they can be used, customized, and extended. Beyond Flask itself, look for community-maintained extensions to add even more functionality. Installation Python Version Dependencies Virtual environments Install Flask Quickstart A Minimal Application Debug Mode HTML Escaping Routing Static Files Rendering Templates Accessing Request Data Redirects and Errors About Responses Sessions Message Flashing Logging Hooking in WSGI Middleware Using Flask Extensions Deploying to a Web Server Tutorial Project Layout Application Setup Define and Access the Database Blueprints and Views Templates Static Files Blog Blueprint Make the Project Installable Test Coverage Deploy to Production Keep Developing! Templates Jinja Setup Standard Context Controlling Autoescaping Registering Filters Context Processors Streaming Testing Flask Applications Identifying Tests Fixtures Sending Requests with the Test Client Following Redirects Accessing and Modifying the Session Running Commands with the CLI Runner Tests that depend on an Active Context Handling Application Errors Error Logging Tools Error Handlers Custom Error Pages Blueprint Error Handlers Returning API Errors as JSON Logging Debugging Debugging Application Errors In Production The Built-In Debugger External Debuggers Logging Basic Configuration Email Errors to Admins Injecting Request Information Other Libraries Configuration Handling Configuration Basics Debug Mode Builtin Configuration Values Configuring from Python Files Configuring from Data Files Configuring from Environment Variables Configuration Best Practices Development / Production Instance Folders Signals Core Signals Subscribing to Signals Creating Signals Sending Signals Signals and Flask’s Request Context Decorator Based Signal Subscriptions Class-based Views Basic Reusable View URL Variables View Lifetime and self View Decorators Method Hints Method Dispatching and APIs Application Structure and Lifecycle Application Setup Serving the Application How a Request is Handled The Application Context Purpose of the Context Lifetime of the Context Manually Push a Context Storing Data Events and Signals The Request Context Purpose of the Context Lifetime of the Context Manually Push a Context How the Context Works Callbacks and Errors Notes On Proxies Modular Applications with Blueprints Why Blueprints? The Concept of Blueprints My First Blueprint Registering Blueprints Nesting Blueprints Blueprint Resources Building URLs Blueprint Error Handlers Extensions Finding Extensions Using Extensions Building Extensions Command Line Interface Application Discovery Run the Development Server Open a Shell Environment Variables From dotenv Environment Variables From virtualenv Custom Commands Plugins Custom Scripts PyCharm Integration Development Server Command Line In Code Working with the Shell Command Line Interface Creating a Request Context Firing Before/After Request Further Improving the Shell Experience Patterns for Flask Large Applications as Packages Application Factories Application Dispatching Using URL Processors Using SQLite 3 with Flask SQLAlchemy in Flask Uploading Files Caching View Decorators Form Validation with WTForms Template Inheritance Message Flashing JavaScript, fetch, and JSON Lazily Loading Views MongoDB with MongoEngine Adding a favicon Streaming Contents Deferred Request Callbacks Adding HTTP Method Overrides Request Content Checksums Background Tasks with Celery Subclassing Flask Single-Page Applications Security Considerations Resource Use Cross-Site Scripting (XSS) Cross-Site Request Forgery (CSRF) JSON Security Security Headers Host Header Validation Copy/Paste to Terminal Deploying to Production Self-Hosted Options Hosting Platforms Async with Gevent Enabling gevent Combining with async/await Using async and await Performance Background tasks When to use Quart instead Extensions Other event loops API Reference¶ If you are looking for information on a specific function, class or method, this part of the documentation is for you. API Application Object Blueprint Objects Incoming Request Data Response Objects Sessions Session Interface Test Client Test CLI Runner Application Globals Useful Functions and Classes Message Flashing JSON Support Template Rendering Configuration Stream Helpers Useful Internals Signals Class-Based Views URL Route Registrations View Function Options Command Line Interface Additional Notes¶ Design Decisions in Flask The Explicit Application Object The Routing System One Template Engine What does “micro” mean? Thread Locals Async/await and ASGI support What Flask is, What Flask is Not Flask Extension Development Naming The Extension Class and Initialization Adding Behavior Configuration Techniques Data During a Request Views and Models Recommended Extension Guidelines Contributing BSD-3-Clause License Changes Version 3.1.3 Version 3.1.2 Version 3.1.1 Version 3.1.0 Version 3.0.3 Version 3.0.2 Version 3.0.1 Version 3.0.0 Version 2.3.3 Version 2.3.2 Version 2.3.1 Version 2.3.0 Version 2.2.5 Version 2.2.4 Version 2.2.3 Version 2.2.2 Version 2.2.1 Version 2.2.0 Version 2.1.3 Version 2.1.2 Version 2.1.1 Version 2.1.0 Version 2.0.3 Version 2.0.2 Version 2.0.1 Version 2.0.0 Version 1.1.4 Version 1.1.3 Version 1.1.2 Version 1.1.1 Version 1.1.0 Version 1.0.4 Version 1.0.3 Version 1.0.2 Version 1.0.1 Version 1.0 Version 0.12.5 Version 0.12.4 Version 0.12.3 Version 0.12.2 Version 0.12.1 Version 0.12 Version 0.11.1 Version 0.11 Version 0.10.1 Version 0.10 Version 0.9 Version 0.8.1 Version 0.8 Version 0.7.2 Version 0.7.1 Version 0.7 Version 0.6.1 Version 0.6 Version 0.5.2 Version 0.5.1 Version 0.5 Version 0.4 Version 0.3.1 Version 0.3 Version 0.2 Version 0.1 Project Links Donate PyPI Releases Source Code Issue Tracker Chat Contents Welcome to Flask User’s Guide API Reference Additional Notes Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.987Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":1700}}19{"id":"doc-deploy_to_production_flask_documentation_3_1_x-9e86792a","source":"documentation","title":"Deploy to Production — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/deploy/","text":"Deploy to Production¶ This part of the tutorial assumes you have a server that you want to deploy your application to. It gives an overview of how to create the distribution file and install it, but won’t go into specifics about what server or software to use. You can set up a new environment on your development computer to try out the instructions below, but probably shouldn’t use it for hosting a real public application. See Deploying to Production for a list of many different ways to host your application. Build and Install¶ When you want to deploy your application elsewhere, you build a wheel (.whl) file. Install and use the build tool to do this. $ pip install build $ python -m build --wheel You can find the file in dist/flaskr-1.0.0-py3-none-any.whl. The file name is in the format of {project name}-{version}-{python tag} -{abi tag}-{platform tag}. Copy this file to another machine, set up a new virtualenv, then install the file with pip. $ pip install flaskr-1.0.0-py3-none-any.whl Pip will install your project along with its dependencies. Since this is a different machine, you need to run init-db again to create the database in the instance folder. $ flask --app flaskr init-db When Flask detects that it’s installed (not in editable mode), it uses a different directory for the instance folder. You can find it at .venv/var/flaskr-instance instead. Configure the Secret Key¶ In the beginning of the tutorial that you gave a default value for SECRET_KEY. This should be changed to some random bytes in production. Otherwise, attackers could use the public 'dev' key to modify the session cookie, or anything else that uses the secret key. You can use the following command to output a random secret key: $ python -c 'import secrets; print(secrets.token_hex())' '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf' Create the config.py file in the instance folder, which the factory will read from if it exists. Copy the generated value into it. .venv/var/flaskr-instance/config.py¶ SECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf' You can also set any other necessary configuration here, although SECRET_KEY is the only one needed for Flaskr. Run with a Production Server¶ When running publicly rather than in development, you should not use the built-in development server (flask run). The development server is provided by Werkzeug for convenience, but is not designed to be particularly efficient, stable, or secure. Instead, use a production WSGI server. For example, to use Waitress, first install it in the virtual environment: $ pip install waitress You need to tell Waitress about your application, but it doesn’t use --app like flask run does. You need to tell it to import and call the application factory to get an application object. $ waitress-serve --call 'flaskr:create_app' Serving on http://0.0.0.0:8080 See Deploying to Production for a list of many different ways to host your application. Waitress is just an example, chosen for the tutorial because it supports both Windows and Linux. There are many more WSGI servers and deployment options that you may choose for your project. Continue to Keep Developing!. Contents Deploy to Production Build and Install Configure the Secret Key Run with a Production Server Navigation Overview Tutorial Coverage Developing! Quick search\n\nExample:\n```text\n$ pip install build\n$ python -m build --wheel\n```\n\nExample:\n```text\n$ pip install flaskr-1.0.0-py3-none-any.whl\n```\n\nExample:\n```text\n$ flask --app flaskr init-db\n```\n\nExample:\n```text\n$ python -c 'import secrets; print(secrets.token_hex())'\n\n'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'\n```\n\nExample:\n```text\nSECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'\n```\n\nExample:\n```text\n$ pip install waitress\n```\n\nExample:\n```text\n$ waitress-serve --call 'flaskr:create_app'\n\nServing on http://0.0.0.0:8080\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.988Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":43,"estimatedTokens":989}}20{"id":"doc-index_flask_documentation_3_1_x-be187b9e","source":"documentation","title":"Index — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/genindex/","text":"Index _ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | Y _ _AppCtxGlobals (class in flask.ctx) A abort() (in module flask) aborter (flask.Flask attribute) aborter_class (flask.Flask attribute) accept_charsets (flask.Request property) accept_encodings (flask.Request property) accept_languages (flask.Request property) accept_mimetypes (flask.Request property) accept_ranges (flask.Response attribute) access_control_allow_credentials (flask.Response property) access_control_allow_headers (flask.Response attribute) access_control_allow_methods (flask.Response attribute) access_control_allow_origin (flask.Response attribute) access_control_expose_headers (flask.Response attribute) access_control_max_age (flask.Response attribute) access_control_request_headers (flask.Request attribute) access_control_request_method (flask.Request attribute) access_route (flask.Request property) accessed (flask.sessions.SessionMixin attribute) add_app_template_filter() (flask.Blueprint method) add_app_template_global() (flask.Blueprint method) add_app_template_test() (flask.Blueprint method) add_etag() (flask.Response method) add_template_filter() (flask.Flask method) add_template_global() (flask.Flask method) add_template_test() (flask.Flask method) add_url_rule() (flask.Blueprint method) (flask.blueprints.BlueprintSetupState method) (flask.Flask method) after_app_request() (flask.Blueprint method) after_request() (flask.Blueprint method) (flask.Flask method) after_request_funcs (flask.Blueprint attribute) (flask.Flask attribute) after_this_request() (in module flask) age (flask.Response attribute) allow (flask.Response property) app (flask.blueprints.BlueprintSetupState attribute) app_context() (flask.Flask method) app_context_processor() (flask.Blueprint method) app_ctx_globals_class (flask.Flask attribute) app_errorhandler() (flask.Blueprint method) app_import_path (flask.cli.ScriptInfo attribute) app_template_filter() (flask.Blueprint method) app_template_global() (flask.Blueprint method) app_template_test() (flask.Blueprint method) app_url_defaults() (flask.Blueprint method) app_url_value_preprocessor() (flask.Blueprint method) AppContext (class in flask.ctx) appcontext_popped (in module flask) appcontext_pushed (in module flask) appcontext_tearing_down (in module flask) AppGroup (class in flask.cli) application() (flask.Request class method) APPLICATION_ROOT (built-in variable) args (flask.Request property) as_view() (flask.views.View class method) async_to_sync() (flask.Flask method) authorization (flask.Request property) auto_find_instance_path() (flask.Flask method) autocorrect_location_header (flask.Response attribute) automatically_set_content_length (flask.Response attribute) B base_url (flask.Request property) before_app_request() (flask.Blueprint method) before_request() (flask.Blueprint method) (flask.Flask method) before_request_funcs (flask.Blueprint attribute) (flask.Flask attribute) Blueprint (class in flask) blueprint (flask.blueprints.BlueprintSetupState attribute) (flask.Request property) blueprints (flask.Flask attribute) (flask.Request property) BlueprintSetupState (class in flask.blueprints) C cache_control (flask.Request property) (flask.Response property) calculate_content_length() (flask.Response method) call_on_close() (flask.Response method) check() (flask.json.tag.JSONTag method) clear() (flask.sessions.NullSession method) cli (flask.Blueprint attribute) (flask.Flask attribute) close() (flask.Request method) (flask.Response method) command() (flask.cli.AppGroup method) compact (flask.json.provider.DefaultJSONProvider attribute) Config (class in flask) config (flask.Flask attribute) config_class (flask.Flask attribute) content_encoding (flask.Request attribute) (flask.Response attribute) content_language (flask.Response property) content_length (flask.Request property) (flask.Response attribute) content_location (flask.Response attribute) content_md5 (flask.Request attribute) (flask.Response attribute) content_range (flask.Response property) content_security_policy (flask.Response property) content_security_policy_report_only (flask.Response property) content_type (flask.Request attribute) (flask.Response attribute) context_processor() (flask.Blueprint method) (flask.Flask method) cookies (flask.Request property) copy() (flask.ctx.RequestContext method) copy_current_request_context() (in module flask) create_app (flask.cli.ScriptInfo attribute) create_global_jinja_loader() (flask.Flask method) create_jinja_environment() (flask.Flask method) create_url_adapter() (flask.Flask method) cross_origin_embedder_policy (flask.Response attribute) cross_origin_opener_policy (flask.Response attribute) current_app (in module flask) D data (flask.cli.ScriptInfo attribute) (flask.Request property) (flask.Response property) date (flask.Request attribute) (flask.Response attribute) DEBUG (built-in variable) debug (flask.Flask property) decorators (flask.views.View attribute) default() (flask.json.provider.DefaultJSONProvider static method) default_mimetype (flask.Response attribute) default_status (flask.Response attribute) default_tags (flask.json.tag.TaggedJSONSerializer attribute) DefaultJSONProvider (class in flask.json.provider) delete() (flask.Blueprint method) (flask.Flask method) delete_cookie() (flask.Response method) dict_storage_class (flask.Request attribute) digest_method() (flask.sessions.SecureCookieSessionInterface static method) direct_passthrough (flask.Response attribute) dispatch_request() (flask.Flask method) (flask.views.MethodView method) (flask.views.View method) do_teardown_appcontext() (flask.Flask method) do_teardown_request() (flask.Flask method) dump() (flask.json.provider.JSONProvider method) (in module flask.json) dumps() (flask.json.provider.DefaultJSONProvider method) (flask.json.provider.JSONProvider method) (flask.json.tag.TaggedJSONSerializer method) (in module flask.json) E endpoint (flask.Request property) endpoint() (flask.Blueprint method) (flask.Flask method) ensure_ascii (flask.json.provider.DefaultJSONProvider attribute) ensure_sync() (flask.Flask method) environ (flask.Request attribute) environment variable FLASK_DEBUG FLASK_ENV YOURAPPLICATION_SETTINGS error_handler_spec (flask.Blueprint attribute) (flask.Flask attribute) errorhandler() (flask.Blueprint method) (flask.Flask method) expires (flask.Response attribute) EXPLAIN_TEMPLATE_LOADING (built-in variable) extensions (flask.Flask attribute) F files (flask.Request property) first_registration (flask.blueprints.BlueprintSetupState attribute) flash() (in module flask) flask module Flask (class in flask) flask.globals.app_ctx (in module flask) flask.globals.request_ctx (in module flask) flask.json module flask.json.tag module FLASK_DEBUG FLASK_ENV FlaskClient (class in flask.testing) FlaskCliRunner (class in flask.testing) FlaskGroup (class in flask.cli) force_type() (flask.Response class method) form (flask.Request property) form_data_parser_class (flask.Request attribute) freeze() (flask.Response method) from_app() (flask.Response class method) from_envvar() (flask.Config method) from_file() (flask.Config method) from_mapping() (flask.Config method) from_object() (flask.Config method) from_prefixed_env() (flask.Config method) from_pyfile() (flask.Config method) from_values() (flask.Request class method) full_dispatch_request() (flask.Flask method) full_path (flask.Request property) G g (in module flask) get() (flask.Blueprint method) (flask.ctx._AppCtxGlobals method) (flask.Flask method) get_app_iter() (flask.Response method) get_command() (flask.cli.FlaskGroup method) get_cookie_domain() (flask.sessions.SessionInterface method) get_cookie_httponly() (flask.sessions.SessionInterface method) get_cookie_name() (flask.sessions.SessionInterface method) get_cookie_partitioned() (flask.sessions.SessionInterface method) get_cookie_path() (flask.sessions.SessionInterface method) get_cookie_samesite() (flask.sessions.SessionInterface method) get_cookie_secure() (flask.sessions.SessionInterface method) get_data() (flask.Request method) (flask.Response method) get_etag() (flask.Response method) get_expiration_time() (flask.sessions.SessionInterface method) get_flashed_messages() (in module flask) get_json() (flask.Request method) (flask.Response method) get_namespace() (flask.Config method) get_send_file_max_age() (flask.Blueprint method) (flask.Flask method) get_template_attribute() (in module flask) get_wsgi_headers() (flask.Response method) get_wsgi_response() (flask.Response method) got_request_exception (in module flask) group() (flask.cli.AppGroup method) H handle_exception() (flask.Flask method) handle_http_exception() (flask.Flask method) handle_url_build_error() (flask.Flask method) handle_user_exception() (flask.Flask method) has_app_context() (in module flask) has_request_context() (in module flask) has_static_folder (flask.Blueprint property) (flask.Flask property) headers (flask.Request attribute) host (flask.Request property) host_url (flask.Request property) I if_match (flask.Request property) if_modified_since (flask.Request property) if_none_match (flask.Request property) if_range (flask.Request property) if_unmodified_since (flask.Request property) implicit_sequence_conversion (flask.Response attribute) import_name (flask.Blueprint attribute) (flask.Flask attribute) init_every_request (flask.views.View attribute) inject_url_defaults() (flask.Flask method) input_stream (flask.Request attribute) instance_path (flask.Flask attribute) invoke() (flask.testing.FlaskCliRunner method) is_json (flask.Request property) (flask.Response property) is_multiprocess (flask.Request attribute) is_multithread (flask.Request attribute) is_null_session() (flask.sessions.SessionInterface method) is_run_once (flask.Request attribute) is_secure (flask.Request property) is_sequence (flask.Response property) is_streamed (flask.Response property) iter_blueprints() (flask.Flask method) iter_encoded() (flask.Response method) J jinja_env (flask.Flask property) jinja_environment (flask.Flask attribute) jinja_loader (flask.Blueprint property) (flask.Flask property) jinja_options (flask.Flask attribute) json (flask.Flask attribute) (flask.Request property) (flask.Response property) json_provider_class (flask.Flask attribute) jsonify() (in module flask.json) JSONProvider (class in flask.json.provider) JSONTag (class in flask.json.tag) K key (flask.json.tag.JSONTag attribute) key_derivation (flask.sessions.SecureCookieSessionInterface attribute) L last_modified (flask.Response attribute) list_commands() (flask.cli.FlaskGroup method) list_storage_class (flask.Request attribute) load() (flask.json.provider.JSONProvider method) (in module flask.json) load_app() (flask.cli.ScriptInfo method) load_dotenv() (in module flask.cli) load_dotenv_defaults (flask.cli.ScriptInfo attribute) loads() (flask.json.provider.DefaultJSONProvider method) (flask.json.provider.JSONProvider method) (flask.json.tag.TaggedJSONSerializer method) (in module flask.json) location (flask.Response attribute) log_exception() (flask.Flask method) logger (flask.Flask property) M make_aborter() (flask.Flask method) make_conditional() (flask.Response method) make_config() (flask.Flask method) make_context() (flask.cli.FlaskGroup method) make_default_options_response() (flask.Flask method) make_form_data_parser() (flask.Request method) make_null_session() (flask.sessions.SessionInterface method) make_response() (flask.Flask method) (in module flask) make_sequence() (flask.Response method) make_setup_state() (flask.Blueprint method) make_shell_context() (flask.Flask method) match_request() (flask.ctx.RequestContext method) MAX_CONTENT_LENGTH (built-in variable) max_content_length (flask.Request property) MAX_COOKIE_SIZE (built-in variable) max_cookie_size (flask.Response property) MAX_FORM_MEMORY_SIZE (built-in variable) max_form_memory_size (flask.Request property) MAX_FORM_PARTS (built-in variable) max_form_parts (flask.Request property) max_forwards (flask.Request attribute) message_flashed (in module flask) method (flask.Request attribute) methods (flask.views.View attribute) MethodView (class in flask.views) mimetype (flask.json.provider.DefaultJSONProvider attribute) (flask.Request property) (flask.Response property) mimetype_params (flask.Request property) (flask.Response property) modified (flask.session attribute) (flask.sessions.SecureCookieSession attribute) (flask.sessions.SessionMixin attribute) module flask flask.json flask.json.tag N name (flask.Flask property) new (flask.session attribute) null_session_class (flask.sessions.SessionInterface attribute) NullSession (class in flask.sessions) O on_json_loading_failed() (flask.Request method) open() (flask.testing.FlaskClient method) open_instance_resource() (flask.Flask method) open_resource() (flask.Blueprint method) (flask.Flask method) open_session() (flask.sessions.SecureCookieSessionInterface method) (flask.sessions.SessionInterface method) options (flask.blueprints.BlueprintSetupState attribute) origin (flask.Request attribute) P parameter_storage_class (flask.Request attribute) pass_script_info() (in module flask.cli) patch() (flask.Blueprint method) (flask.Flask method) path (flask.Request attribute) permanent (flask.session attribute) (flask.sessions.SessionMixin property) PERMANENT_SESSION_LIFETIME (built-in variable) permanent_session_lifetime (flask.Flask attribute) pickle_based (flask.sessions.SessionInterface attribute) pop() (flask.ctx._AppCtxGlobals method) (flask.ctx.AppContext method) (flask.ctx.RequestContext method) (flask.sessions.NullSession method) popitem() (flask.sessions.NullSession method) post() (flask.Blueprint method) (flask.Flask method) pragma (flask.Request property) PREFERRED_URL_SCHEME (built-in variable) preprocess_request() (flask.Flask method) process_response() (flask.Flask method) PROPAGATE_EXCEPTIONS (built-in variable) PROVIDE_AUTOMATIC_OPTIONS (built-in variable) provide_automatic_options (flask.views.View attribute) push() (flask.ctx.AppContext method) put() (flask.Blueprint method) (flask.Flask method) Python Enhancement Proposals PEP 302 PEP 3333, [1] PEP 451 PEP 519 Q query_string (flask.Request attribute) R range (flask.Request property) record() (flask.Blueprint method) record_once() (flask.Blueprint method) redirect() (flask.Flask method) (in module flask) referrer (flask.Request attribute) register() (flask.Blueprint method) (flask.json.tag.TaggedJSONSerializer method) register_blueprint() (flask.Blueprint method) (flask.Flask method) register_error_handler() (flask.Blueprint method) (flask.Flask method) remote_addr (flask.Request attribute) remote_user (flask.Request attribute) render_template() (in module flask) render_template_string() (in module flask) Request (class in flask) request (in module flask) request_class (flask.Flask attribute) request_context() (flask.Flask method) request_finished (in module flask) request_started (in module flask) request_tearing_down (in module flask) RequestContext (class in flask.ctx) Response (class in flask) response (flask.Response attribute) response() (flask.json.provider.DefaultJSONProvider method) (flask.json.provider.JSONProvider method) response_class (flask.Flask attribute) retry_after (flask.Response property) RFC RFC 2231 RFC 822 RFC 8259, [1] root_path (flask.Blueprint attribute) (flask.Flask attribute) (flask.Request attribute) root_url (flask.Request property) route() (flask.Blueprint method) (flask.Flask method) routing_exception (flask.Request attribute) run() (flask.Flask method) run_command (in module flask.cli) S salt (flask.sessions.SecureCookieSessionInterface attribute) save_session() (flask.sessions.SecureCookieSessionInterface method) (flask.sessions.SessionInterface method) scheme (flask.Request attribute) script_root (flask.Request property) ScriptInfo (class in flask.cli) SECRET_KEY (built-in variable) secret_key (flask.Flask attribute) SECRET_KEY_FALLBACKS (built-in variable) SecureCookieSession (class in flask.sessions) SecureCookieSessionInterface (class in flask.sessions) select_jinja_autoescape() (flask.Flask method) send_file() (in module flask) SEND_FILE_MAX_AGE_DEFAULT (built-in variable) send_from_directory() (in module flask) send_static_file() (flask.Blueprint method) (flask.Flask method) serializer (flask.sessions.SecureCookieSessionInterface attribute) server (flask.Request attribute) SERVER_NAME (built-in variable) session (class in flask) (flask.ctx.RequestContext property) session_class (flask.sessions.SecureCookieSessionInterface attribute) SESSION_COOKIE_DOMAIN (built-in variable) SESSION_COOKIE_HTTPONLY (built-in variable) SESSION_COOKIE_NAME (built-in variable) SESSION_COOKIE_PARTITIONED (built-in variable) SESSION_COOKIE_PATH (built-in variable) SESSION_COOKIE_SAMESITE (built-in variable) SESSION_COOKIE_SECURE (built-in variable) session_interface (flask.Flask attribute) SESSION_REFRESH_EACH_REQUEST (built-in variable) session_transaction() (flask.testing.FlaskClient method) SessionInterface (class in flask.sessions) SessionMixin (class in flask.sessions) set_cookie() (flask.Response method) set_data() (flask.Response method) set_etag() (flask.Response method) setdefault() (flask.ctx._AppCtxGlobals method) (flask.sessions.NullSession method) shallow (flask.Request attribute) shell_command (in module flask.cli) shell_context_processor() (flask.Flask method) shell_context_processors (flask.Flask attribute) should_ignore_error() (flask.Flask method) should_set_cookie() (flask.sessions.SessionInterface method) sort_keys (flask.json.provider.DefaultJSONProvider attribute) static_folder (flask.Blueprint property) (flask.Flask property) static_url_path (flask.Blueprint property) (flask.Flask property) status (flask.Response property) status_code (flask.Response property) stream (flask.Request property) (flask.Response property) stream_template() (in module flask) stream_template_string() (in module flask) stream_with_context() (in module flask) subdomain (flask.blueprints.BlueprintSetupState attribute) T tag() (flask.json.tag.JSONTag method) (flask.json.tag.TaggedJSONSerializer method) TaggedJSONSerializer (class in flask.json.tag) teardown_app_request() (flask.Blueprint method) teardown_appcontext() (flask.Flask method) teardown_appcontext_funcs (flask.Flask attribute) teardown_request() (flask.Blueprint method) (flask.Flask method) teardown_request_funcs (flask.Blueprint attribute) (flask.Flask attribute) template_context_processors (flask.Blueprint attribute) (flask.Flask attribute) template_filter() (flask.Flask method) template_folder (flask.Blueprint attribute) (flask.Flask attribute) template_global() (flask.Flask method) template_rendered (in module flask) template_test() (flask.Flask method) TEMPLATES_AUTO_RELOAD (built-in variable) test_cli_runner() (flask.Flask method) test_cli_runner_class (flask.Flask attribute) test_client() (flask.Flask method) test_client_class (flask.Flask attribute) test_request_context() (flask.Flask method) TESTING (built-in variable) testing (flask.Flask attribute) to_json() (flask.json.tag.JSONTag method) to_python() (flask.json.tag.JSONTag method) TRAP_BAD_REQUEST_ERRORS (built-in variable) trap_http_exception() (flask.Flask method) TRAP_HTTP_EXCEPTIONS (built-in variable) TRUSTED_HOSTS (built-in variable) trusted_hosts (flask.Request attribute) U untag() (flask.json.tag.TaggedJSONSerializer method) update() (flask.sessions.NullSession method) update_template_context() (flask.Flask method) url (flask.Request property) url_build_error_handlers (flask.Flask attribute) url_default_functions (flask.Blueprint attribute) (flask.Flask attribute) url_defaults (flask.blueprints.BlueprintSetupState attribute) url_defaults() (flask.Blueprint method) (flask.Flask method) url_for() (flask.Flask method) (in module flask) url_map (flask.Flask attribute) url_map_class (flask.Flask attribute) url_prefix (flask.blueprints.BlueprintSetupState attribute) url_root (flask.Request property) url_rule (flask.Request attribute) url_rule_class (flask.Flask attribute) url_value_preprocessor() (flask.Blueprint method) (flask.Flask method) url_value_preprocessors (flask.Blueprint attribute) (flask.Flask attribute) USE_X_SENDFILE (built-in variable) user_agent (flask.Request property) user_agent_class (flask.Request attribute) V values (flask.Request property) vary (flask.Response property) View (class in flask.views) view_args (flask.Request attribute) view_functions (flask.Blueprint attribute) (flask.Flask attribute) W want_form_data_parsed (flask.Request property) with_appcontext() (in module flask.cli) wsgi_app() (flask.Flask method) www_authenticate (flask.Response property) Y YOURAPPLICATION_SETTINGS Navigation Overview Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:32.990Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":5206}}21{"id":"doc-patterns_for_flask_flask_documentation_3_1_x-e98d46df","source":"documentation","title":"Patterns for Flask — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/","text":"Patterns for Flask¶ Certain features and interactions are common enough that you will find them in most web applications. For example, many applications use a relational database and user authentication. They will open a database connection at the beginning of the request and get the information for the logged in user. At the end of the request, the database connection is closed. These types of patterns may be a bit outside the scope of Flask itself, but Flask makes it easy to implement them. Some common patterns are collected in the following pages. Large Applications as Packages Simple Packages Working with Blueprints Application Factories Basic Factories Factories & Extensions Using Applications Factory Improvements Application Dispatching Working with this Document Combining Applications Dispatch by Subdomain Dispatch by Path Using URL Processors Internationalized Application URLs Internationalized Blueprint URLs Using SQLite 3 with Flask Connect on Demand Easy Querying Initial Schemas SQLAlchemy in Flask Flask-SQLAlchemy Extension Declarative Manual Object Relational Mapping SQL Abstraction Layer Uploading Files A Gentle Introduction Improving Uploads Upload Progress Bars An Easier Solution Caching View Decorators Login Required Decorator Caching Decorator Templating Decorator Endpoint Decorator Form Validation with WTForms The Forms In the View Forms in Templates Template Inheritance Base Template Child Template Message Flashing Simple Flashing Flashing With Categories Filtering Flash Messages JavaScript, fetch, and JSON Rendering Templates Generating URLs Making a Request with fetch Following Redirects Replacing Content Return JSON from Views Receiving JSON in Views Lazily Loading Views Converting to Centralized URL Map Loading Late MongoDB with MongoEngine Configuration Mapping Documents Creating Data Queries Documentation Adding a favicon See also Streaming Contents HTTP Response Behavior Basic Usage Streaming from Templates Streaming with Context Deferred Request Callbacks Adding HTTP Method Overrides Request Content Checksums Background Tasks with Celery Install Integrate Celery with Flask Application Factory Defining Tasks Calling Tasks Getting Results Passing Data to Tasks Subclassing Flask Single-Page Applications Navigation Overview with the Shell Applications as Packages Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.052Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":589}}22{"id":"doc-project_layout_flask_documentation_3_1_x-65dd6484","source":"documentation","title":"Project Layout — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/layout/","text":"Project Layout¶ Create a project directory and enter it: $ mkdir flask-tutorial $ cd flask-tutorial Then follow the installation instructions to set up a Python virtual environment and install Flask for your project. The tutorial will assume you’re working from the flask-tutorial directory from now on. The file names at the top of each code block are relative to this directory. A Flask application can be as simple as a single file. hello.py¶ from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello, World!' However, as a project gets bigger, it becomes overwhelming to keep all the code in one file. Python projects use packages to organize code into multiple modules that can be imported where needed, and the tutorial will do this as well. The project directory will /, a Python package containing your application code and files. tests/, a directory containing test modules. .venv/, a Python virtual environment where Flask and other dependencies are installed. Installation files telling Python how to install your project. Version control config, such as git. You should make a habit of using some type of version control for all your projects, no matter the size. Any other project files you might add in the future. By the end, your project layout will look like this: /home/user/Projects/flask-tutorial ├── flaskr/ │ ├── __init__.py │ ├── db.py │ ├── schema.sql │ ├── auth.py │ ├── blog.py │ ├── templates/ │ │ ├── base.html │ │ ├── auth/ │ │ │ ├── login.html │ │ │ └── register.html │ │ └── blog/ │ │ ├── create.html │ │ ├── index.html │ │ └── update.html │ └── static/ │ └── style.css ├── tests/ │ ├── conftest.py │ ├── data.sql │ ├── test_factory.py │ ├── test_db.py │ ├── test_auth.py │ └── test_blog.py ├── .venv/ ├── pyproject.toml └── MANIFEST.in If you’re using version control, the following files that are generated while running your project should be ignored. There may be other files based on the editor you use. In general, ignore files that you didn’t write. For example, with ¶ .venv/ *.pyc __pycache__/ instance/ .pytest_cache/ .coverage htmlcov/ dist/ build/ *.egg-info/ Continue to Application Setup. Navigation Overview Tutorial Setup Quick search\n\nExample:\n```text\n$ mkdir flask-tutorial\n$ cd flask-tutorial\n```\n\nExample:\n```text\nfrom flask import Flask\n\napp = Flask(__name__)\n\n\n@app.route('/')\ndef hello():\n    return 'Hello, World!'\n```\n\nExample:\n```text\n/home/user/Projects/flask-tutorial\n├── flaskr/\n│   ├── __init__.py\n│   ├── db.py\n│   ├── schema.sql\n│   ├── auth.py\n│   ├── blog.py\n│   ├── templates/\n│   │   ├── base.html\n│   │   ├── auth/\n│   │   │   ├── login.html\n│   │   │   └── register.html\n│   │   └── blog/\n│   │       ├── create.html\n│   │       ├── index.html\n│   │       └── update.html\n│   └── static/\n│       └── style.css\n├── tests/\n│   ├── conftest.py\n│   ├── data.sql\n│   ├── test_factory.py\n│   ├── test_db.py\n│   ├── test_auth.py\n│   └── test_blog.py\n├── .venv/\n├── pyproject.toml\n└── MANIFEST.in\n```\n\nExample:\n```text\n.venv/\n\n*.pyc\n__pycache__/\n\ninstance/\n\n.pytest_cache/\n.coverage\nhtmlcov/\n\ndist/\nbuild/\n*.egg-info/\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.052Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":71,"estimatedTokens":782}}23{"id":"doc-keep_developing_flask_documentation_3_1_x-038b2c59","source":"documentation","title":"Keep Developing! — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/next/","text":"Keep Developing!¶ You’ve learned about quite a few Flask and Python concepts throughout the tutorial. Go back and review the tutorial and compare your code with the steps you took to get there. Compare your project to the example project, which might look a bit different due to the step-by-step nature of the tutorial. There’s a lot more to Flask than what you’ve seen so far. Even so, you’re now equipped to start developing your own web applications. Check out the Quickstart for an overview of what Flask can do, then dive into the docs to keep learning. Flask uses Jinja, Click, Werkzeug, and ItsDangerous behind the scenes, and they all have their own documentation too. You’ll also be interested in Extensions which make tasks like working with the database or validating form data easier and more powerful. If you want to keep developing your Flaskr project, here are some ideas for what to try detail view to show a single post. Click a post’s title to go to its page. Like / unlike a post. Comments. Tags. Clicking a tag shows all the posts with that tag. A search box that filters the index page by name. Paged display. Only show 5 posts per page. Upload an image to go along with a post. Format posts using Markdown. An RSS feed of new posts. Have fun and make awesome applications! Navigation Overview Tutorial to Production Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.053Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":341}}24{"id":"doc-make_the_project_installable_flask_documentation-87e02393","source":"documentation","title":"Make the Project Installable — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/install/","text":"Make the Project Installable¶ Making your project installable means that you can build a wheel file and install that in another environment, just like you installed Flask in your project’s environment. This makes deploying your project the same as installing any other library, so you’re using all the standard Python tools to manage everything. Installing also comes with other benefits that might not be obvious from the tutorial or as a new Python user, , Python and Flask understand how to use the flaskr package only because you’re running from your project’s directory. Installing means you can import it no matter where you run from. You can manage your project’s dependencies just like other packages do, so pip install yourproject.whl installs them. Test tools can isolate your test environment from your development environment. Note This is being introduced late in the tutorial, but in your future projects you should always start with this. Describe the Project¶ The pyproject.toml file describes your project and how to build it. pyproject.toml¶ [project] name = \"flaskr\" version = \"1.0.0\" description = \"The basic blog app built in the Flask tutorial.\" dependencies = [ \"flask\", ] [build-system] requires = [\"flit_core<4\"] build-backend = \"flit_core.buildapi\" See the official Packaging tutorial for more explanation of the files and options used. Install the Project¶ Use pip to install your project in the virtual environment. $ pip install -e . This tells pip to find pyproject.toml in the current directory and install the project in editable or development mode. Editable mode means that as you make changes to your local code, you’ll only need to re-install if you change the metadata about the project, such as its dependencies. You can observe that the project is now installed with pip list. $ pip list Package Version Location -------------- --------- ---------------------------------- click 6.7 Flask 1.0 flaskr 1.0.0 /home/user/Projects/flask-tutorial itsdangerous 0.24 Jinja2 2.10 MarkupSafe 1.0 pip 9.0.3 Werkzeug 0.14.1 Nothing changes from how you’ve been running your project so far. --app is still set to flaskr and flask run still runs the application, but you can call it from anywhere, not just the flask-tutorial directory. Continue to Test Coverage. Contents Make the Project Installable Describe the Project Install the Project Navigation Overview Tutorial Blueprint Coverage Quick search\n\nExample:\n```text\n[project]\nname = \"flaskr\"\nversion = \"1.0.0\"\ndescription = \"The basic blog app built in the Flask tutorial.\"\ndependencies = [\n    \"flask\",\n]\n\n[build-system]\nrequires = [\"flit_core<4\"]\nbuild-backend = \"flit_core.buildapi\"\n```\n\nExample:\n```text\n$ pip install -e .\n```\n\nExample:\n```text\n$ pip list\n\nPackage        Version   Location\n-------------- --------- ----------------------------------\nclick          6.7\nFlask          1.0\nflaskr         1.0.0     /home/user/Projects/flask-tutorial\nitsdangerous   0.24\nJinja2         2.10\nMarkupSafe     1.0\npip            9.0.3\nWerkzeug       0.14.1\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.053Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":3,"totalLines":39,"estimatedTokens":764}}25{"id":"doc-templates_flask_documentation_3_1_x-4915efb4","source":"documentation","title":"Templates — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/templates/","text":"Example:\n```text\n<!doctype html>\n<title>{% block title %}{% endblock %} - Flaskr</title>\n<link rel=\"stylesheet\" href=\"{{ url_for('static', filename='style.css') }}\">\n<nav>\n  <h1>Flaskr</h1>\n  <ul>\n    {% if g.user %}\n      <li><span>{{ g.user['username'] }}</span>\n      <li><a href=\"{{ url_for('auth.logout') }}\">Log Out</a>\n    {% else %}\n      <li><a href=\"{{ url_for('auth.register') }}\">Register</a>\n      <li><a href=\"{{ url_for('auth.login') }}\">Log In</a>\n    {% endif %}\n  </ul>\n</nav>\n<section class=\"content\">\n  <header>\n    {% block header %}{% endblock %}\n  </header>\n  {% for message in get_flashed_messages() %}\n    <div class=\"flash\">{{ message }}</div>\n  {% endfor %}\n  {% block content %}{% endblock %}\n</section>\n```\n\nExample:\n```text\n{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}Register{% endblock %}</h1>\n{% endblock %}\n\n{% block content %}\n  <form method=\"post\">\n    <label for=\"username\">Username</label>\n    <input name=\"username\" id=\"username\" required>\n    <label for=\"password\">Password</label>\n    <input type=\"password\" name=\"password\" id=\"password\" required>\n    <input type=\"submit\" value=\"Register\">\n  </form>\n{% endblock %}\n```\n\nExample:\n```text\n{% extends 'base.html' %}\n\n{% block header %}\n  <h1>{% block title %}Log In{% endblock %}</h1>\n{% endblock %}\n\n{% block content %}\n  <form method=\"post\">\n    <label for=\"username\">Username</label>\n    <input name=\"username\" id=\"username\" required>\n    <label for=\"password\">Password</label>\n    <input type=\"password\" name=\"password\" id=\"password\" required>\n    <input type=\"submit\" value=\"Log In\">\n  </form>\n{% endblock %}\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.053Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":3,"totalLines":67,"estimatedTokens":412}}26{"id":"doc-define_and_access_the_database_flask_documentati-a6802489","source":"documentation","title":"Define and Access the Database — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/database/","text":"Example:\n```text\nimport sqlite3\nfrom datetime import datetime\n\nimport click\nfrom flask import current_app, g\n\n\ndef get_db():\n    if 'db' not in g:\n        g.db = sqlite3.connect(\n            current_app.config['DATABASE'],\n            detect_types=sqlite3.PARSE_DECLTYPES\n        )\n        g.db.row_factory = sqlite3.Row\n\n    return g.db\n\n\ndef close_db(e=None):\n    db = g.pop('db', None)\n\n    if db is not None:\n        db.close()\n```\n\nExample:\n```text\nDROP TABLE IF EXISTS user;\nDROP TABLE IF EXISTS post;\n\nCREATE TABLE user (\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\n  username TEXT UNIQUE NOT NULL,\n  password TEXT NOT NULL\n);\n\nCREATE TABLE post (\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\n  author_id INTEGER NOT NULL,\n  created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  title TEXT NOT NULL,\n  body TEXT NOT NULL,\n  FOREIGN KEY (author_id) REFERENCES user (id)\n);\n```\n\nExample:\n```text\ndef init_db():\n    db = get_db()\n\n    with current_app.open_resource('schema.sql') as f:\n        db.executescript(f.read().decode('utf8'))\n\n\n@click.command('init-db')\ndef init_db_command():\n    \"\"\"Clear the existing data and create new tables.\"\"\"\n    init_db()\n    click.echo('Initialized the database.')\n\n\nsqlite3.register_converter(\n    \"timestamp\", lambda v: datetime.fromisoformat(v.decode())\n)\n```\n\nExample:\n```text\ndef init_app(app):\n    app.teardown_appcontext(close_db)\n    app.cli.add_command(init_db_command)\n```\n\nExample:\n```text\ndef create_app():\n    app = ...\n    # existing code omitted\n\n    from . import db\n    db.init_app(app)\n\n    return app\n```\n\nExample:\n```text\n$ flask --app flaskr init-db\nInitialized the database.\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.054Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":6,"totalLines":95,"estimatedTokens":412}}27{"id":"doc-application_setup_flask_documentation_3_1_x-2e35bbc5","source":"documentation","title":"Application Setup — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/factory/","text":"Example:\n```text\n$ mkdir flaskr\n```\n\nExample:\n```text\nimport os\n\nfrom flask import Flask\n\n\ndef create_app(test_config=None):\n    # create and configure the app\n    app = Flask(__name__, instance_relative_config=True)\n    app.config.from_mapping(\n        SECRET_KEY='dev',\n        DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),\n    )\n\n    if test_config is None:\n        # load the instance config, if it exists, when not testing\n        app.config.from_pyfile('config.py', silent=True)\n    else:\n        # load the test config if passed in\n        app.config.from_mapping(test_config)\n\n    # ensure the instance folder exists\n    os.makedirs(app.instance_path, exist_ok=True)\n\n    # a simple page that says hello\n    @app.route('/hello')\n    def hello():\n        return 'Hello, World!'\n\n    return app\n```\n\nExample:\n```text\n$ flask --app flaskr run --debug\n```\n\nExample:\n```text\n* Serving Flask app \"flaskr\"\n* Debug mode: on\n* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n* Restarting with stat\n* Debugger is active!\n* Debugger PIN: nnn-nnn-nnn\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.054Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":4,"totalLines":54,"estimatedTokens":272}}28{"id":"doc-blueprints_and_views_flask_documentation_3_1_x-1f2ce6d3","source":"documentation","title":"Blueprints and Views — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/views/","text":"Example:\n```text\nimport functools\n\nfrom flask import (\n    Blueprint, flash, g, redirect, render_template, request, session, url_for\n)\nfrom werkzeug.security import check_password_hash, generate_password_hash\n\nfrom flaskr.db import get_db\n\nbp = Blueprint('auth', __name__, url_prefix='/auth')\n```\n\nExample:\n```text\ndef create_app():\n    app = ...\n    # existing code omitted\n\n    from . import auth\n    app.register_blueprint(auth.bp)\n\n    return app\n```\n\nExample:\n```text\n@bp.route('/register', methods=('GET', 'POST'))\ndef register():\n    if request.method == 'POST':\n        username = request.form['username']\n        password = request.form['password']\n        db = get_db()\n        error = None\n\n        if not username:\n            error = 'Username is required.'\n        elif not password:\n            error = 'Password is required.'\n\n        if error is None:\n            try:\n                db.execute(\n                    \"INSERT INTO user (username, password) VALUES (?, ?)\",\n                    (username, generate_password_hash(password)),\n                )\n                db.commit()\n            except db.IntegrityError:\n                error = f\"User {username} is already registered.\"\n            else:\n                return redirect(url_for(\"auth.login\"))\n\n        flash(error)\n\n    return render_template('auth/register.html')\n```\n\nExample:\n```text\n@bp.route('/login', methods=('GET', 'POST'))\ndef login():\n    if request.method == 'POST':\n        username = request.form['username']\n        password = request.form['password']\n        db = get_db()\n        error = None\n        user = db.execute(\n            'SELECT * FROM user WHERE username = ?', (username,)\n        ).fetchone()\n\n        if user is None:\n            error = 'Incorrect username.'\n        elif not check_password_hash(user['password'], password):\n            error = 'Incorrect password.'\n\n        if error is None:\n            session.clear()\n            session['user_id'] = user['id']\n            return redirect(url_for('index'))\n\n        flash(error)\n\n    return render_template('auth/login.html')\n```\n\nExample:\n```text\n@bp.before_app_request\ndef load_logged_in_user():\n    user_id = session.get('user_id')\n\n    if user_id is None:\n        g.user = None\n    else:\n        g.user = get_db().execute(\n            'SELECT * FROM user WHERE id = ?', (user_id,)\n        ).fetchone()\n```\n\nExample:\n```text\n@bp.route('/logout')\ndef logout():\n    session.clear()\n    return redirect(url_for('index'))\n```\n\nExample:\n```text\ndef login_required(view):\n    @functools.wraps(view)\n    def wrapped_view(**kwargs):\n        if g.user is None:\n            return redirect(url_for('auth.login'))\n\n        return view(**kwargs)\n\n    return wrapped_view\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.055Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":122,"estimatedTokens":688}}29{"id":"doc-extensions_flask_documentation_3_1_x-6f9f12e5","source":"documentation","title":"Extensions — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/extensions/","text":"Extensions¶ Extensions are extra packages that add functionality to a Flask application. For example, an extension might add support for sending email or connecting to a database. Some extensions add entire new frameworks to help build certain types of applications, like a REST API. Finding Extensions¶ Flask extensions are usually named “Flask-Foo” or “Foo-Flask”. You can search PyPI for packages tagged with Framework :: Flask. Using Extensions¶ Consult each extension’s documentation for installation, configuration, and usage instructions. Generally, extensions pull their own configuration from app.config and are passed an application instance during initialization. For example, an extension called “Flask-Foo” might be used like flask_foo import Foo foo = Foo() app = Flask(__name__) app.config.update( FOO_BAR='baz', FOO_SPAM='eggs', ) foo.init_app(app) Building Extensions¶ While PyPI contains many Flask extensions, you may not find an extension that fits your need. If this is the case, you can create your own, and publish it for others to use as well. Read Flask Extension Development to develop your own Flask extension. Contents Extensions Finding Extensions Using Extensions Building Extensions Navigation Overview Applications with Blueprints Line Interface Quick search\n\nExample:\n```text\nfrom flask_foo import Foo\n\nfoo = Foo()\n\napp = Flask(__name__)\napp.config.update(\n    FOO_BAR='baz',\n    FOO_SPAM='eggs',\n)\n\nfoo.init_app(app)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.055Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":1,"totalLines":18,"estimatedTokens":367}}30{"id":"doc-debugging_application_errors_flask_documentation-1b137210","source":"documentation","title":"Debugging Application Errors — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/debugging/","text":"Debugging Application Errors¶ In Production¶ Do not run the development server, or enable the built-in debugger, in a production environment. The debugger allows executing arbitrary Python code from the browser. It’s protected by a pin, but that should not be relied on for security. Use an error logging tool, such as Sentry, as described in Error Logging Tools, or enable logging and notifications as described in Logging. If you have access to the server, you could add some code to start an external debugger if request.remote_addr matches your IP. Some IDE debuggers also have a remote mode so breakpoints on the server can be interacted with locally. Only enable a debugger temporarily. The Built-In Debugger¶ The built-in Werkzeug development server provides a debugger which shows an interactive traceback in the browser when an unhandled error occurs during a request. This debugger should only be used during development. Warning The debugger allows executing arbitrary Python code from the browser. It is protected by a pin, but still represents a major security risk. Do not run the development server or debugger in a production environment. The debugger is enabled by default when the development server is run in debug mode. $ flask --app hello run --debug When running from Python code, passing debug=True enables debug mode, which is mostly equivalent. app.run(debug=True) Development Server and Command Line Interface have more information about running the debugger and debug mode. More information about the debugger can be found in the Werkzeug documentation. External Debuggers¶ External debuggers, such as those provided by IDEs, can offer a more powerful debugging experience than the built-in debugger. They can also be used to step through code during a request before an error is raised, or if no error is raised. Some even have a remote mode so you can debug code running on another machine. When using an external debugger, the app should still be in debug mode, otherwise Flask turns unhandled errors into generic 500 error pages. However, the built-in debugger and reloader should be disabled so they don’t interfere with the external debugger. $ flask --app hello run --debug --no-debugger --no-reload When running from (debug=True, use_debugger=False, use_reloader=False) Disabling these isn’t required, an external debugger will continue to work with the following caveats. If the built-in debugger is not disabled, it will catch unhandled exceptions before the external debugger can. If the reloader is not disabled, it could cause an unexpected reload if code changes during a breakpoint. The development server will still catch unhandled exceptions if the built-in debugger is disabled, otherwise it would crash on any error. If you want that (and usually you don’t) pass passthrough_errors=True to app.run. app.run( debug=True, passthrough_errors=True, use_debugger=False, use_reloader=False ) Contents Debugging Application Errors In Production The Built-In Debugger External Debuggers Navigation Overview Application Errors Quick search\n\nExample:\n```text\n$ flask --app hello run --debug\n```\n\nExample:\n```text\napp.run(debug=True)\n```\n\nExample:\n```text\n$ flask --app hello run --debug --no-debugger --no-reload\n```\n\nExample:\n```text\napp.run(debug=True, use_debugger=False, use_reloader=False)\n```\n\nExample:\n```text\napp.run(\n    debug=True, passthrough_errors=True,\n    use_debugger=False, use_reloader=False\n)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.055Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":5,"totalLines":31,"estimatedTokens":867}}31{"id":"doc-development_server_flask_documentation_3_1_x-1639c945","source":"documentation","title":"Development Server — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/server/","text":"Development Server¶ Flask provides a run command to run the application with a development server. In debug mode, this server provides an interactive debugger and will reload when code is changed. Warning Do not use the development server when deploying to production. It is intended for use only during local development. It is not designed to be particularly efficient, stable, or secure. See Deploying to Production for deployment options. Command Line¶ The flask run CLI command is the recommended way to run the development server. Use the --app option to point to your application, and the --debug option to enable debug mode. $ flask --app hello run --debug This enables debug mode, including the interactive debugger and reloader, and then starts the server on http://localhost:5000/. Use flask run --help to see the available options, and Command Line Interface for detailed instructions about configuring and using the CLI. Address already in use¶ If another program is already using port 5000, you’ll see an OSError when the server tries to start. It may have one of the following : [Errno 98] Address already in use OSError: [WinError 10013] An attempt was made to access a socket in a way forbidden by its access permissions Either identify and stop the other program, or use flask run --port 5001 to pick a different port. You can use netstat or lsof to identify what process id is using a port, then use other operating system tools stop that process. The following example shows that process id 6847 is using port 5000. netstat (Linux)lsof (macOS / Linux)netstat (Windows)$ netstat -nlp | grep 5000 tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 6847/python $ lsof -P Python 6847 IPv4 TCP (LISTEN) > netstat -ano | findstr 5000 TCP 127.0.0.1:5000 0.0.0.0:0 LISTENING 6847 macOS Monterey and later automatically starts a service that uses port 5000. You can choose to disable this service instead of using a different port by searching for “AirPlay Receiver” in System Settings and toggling it off. Deferred Errors on Reload¶ When using the flask run command with the reloader, the server will continue to run even if you introduce syntax errors or other initialization errors into the code. Accessing the site will show the interactive debugger for the error, rather than crashing the server. If a syntax error is already present when calling flask run, it will fail immediately and show the traceback rather than waiting until the site is accessed. This is intended to make errors more visible initially while still allowing the server to handle errors on reload. In Code¶ The development server can also be started from Python with the Flask.run() method. This method takes arguments similar to the CLI options to control the server. The main difference from the CLI command is that the server will crash if there are errors when reloading. debug=True can be passed to enable debug mode. Place the call in a main block, otherwise it will interfere when trying to import and run the application with a production server later. if __name__ == \"__main__\": app.run(debug=True) $ python hello.py Contents Development Server Command Line Address already in use Deferred Errors on Reload In Code Navigation Overview Line Interface with the Shell Quick search\n\nExample:\n```text\n$ flask --app hello run --debug\n```\n\nExample:\n```text\n$ netstat -nlp | grep 5000\ntcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 6847/python\n```\n\nExample:\n```text\n$ lsof -P -i :5000\nPython 6847 IPv4 TCP localhost:5000 (LISTEN)\n```\n\nExample:\n```text\n> netstat -ano | findstr 5000\nTCP 127.0.0.1:5000 0.0.0.0:0 LISTENING 6847\n```\n\nExample:\n```text\nif __name__ == \"__main__\":\n    app.run(debug=True)\n```\n\nExample:\n```text\n$ python hello.py\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.055Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":37,"estimatedTokens":932}}32{"id":"doc-the_application_context_flask_documentation_3_1_-a9543e69","source":"documentation","title":"The Application Context — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/appcontext/","text":"The Application Context¶ The application context keeps track of the application-level data during a request, CLI command, or other activity. Rather than passing the application around to each function, the current_app and g proxies are accessed instead. This is similar to The Request Context, which keeps track of request-level data during a request. A corresponding application context is pushed when a request context is pushed. Purpose of the Context¶ The Flask application object has attributes, such as config, that are useful to access within views and CLI commands. However, importing the app instance within the modules in your project is prone to circular import issues. When using the app factory pattern or writing reusable blueprints or extensions there won’t be an app instance to import at all. Flask solves this issue with the application context. Rather than referring to an app directly, you use the current_app proxy, which points to the application handling the current activity. Flask automatically pushes an application context when handling a request. View functions, error handlers, and other functions that run during a request will have access to current_app. Flask will also automatically push an app context when running CLI commands registered with Flask.cli using @app.cli.command(). Lifetime of the Context¶ The application context is created and destroyed as necessary. When a Flask application begins handling a request, it pushes an application context and a request context. When the request ends it pops the request context then the application context. Typically, an application context will have the same lifetime as a request. See The Request Context for more information about how the contexts work and the full life cycle of a request. Manually Push a Context¶ If you try to access current_app, or anything that uses it, outside an application context, you’ll get this error : Working outside of application context. This typically means that you attempted to use functionality that needed to interface with the current application object in some way. To solve this, set up an application context with app.app_context(). If you see that error while configuring your application, such as when initializing an extension, you can push a context manually since you have direct access to the app. Use app_context() in a with block, and everything that runs in the block will have access to current_app. def create_app(): app = Flask(__name__) with app.app_context(): init_db() return app If you see that error somewhere else in your code not related to configuring the application, it most likely indicates that you should move that code into a view function or CLI command. Storing Data¶ The application context is a good place to store common data during a request or CLI command. Flask provides the g object for this purpose. It is a simple namespace object that has the same lifetime as an application context. Note The g name stands for “global”, but that is referring to the data being global within a context. The data on g is lost after the context ends, and it is not an appropriate place to store data between requests. Use the session or a database to store data across requests. A common use for g is to manage resources during a request. get_X() creates resource X if it does not exist, caching it as g.X. teardown_X() closes or otherwise deallocates the resource if it exists. It is registered as a teardown_appcontext() handler. For example, you can manage a database connection using this flask import g def get_db(): if 'db' not in = connect_to_database() return g.db @app.teardown_appcontext def teardown_db(exception): db = g.pop('db', None) if db is not () During a request, every call to get_db() will return the same connection, and it will be closed automatically at the end of the request. You can use LocalProxy to make a new context local from get_db(): from werkzeug.local import LocalProxy db = LocalProxy(get_db) Accessing db will call get_db internally, in the same way that current_app works. Events and Signals¶ The application will call functions registered with teardown_appcontext() when the application context is popped. The following signals are , appcontext_tearing_down, and appcontext_popped. Contents The Application Context Purpose of the Context Lifetime of the Context Manually Push a Context Storing Data Events and Signals Navigation Overview Structure and Lifecycle Request Context Quick search\n\nExample:\n```text\nRuntimeError: Working outside of application context.\n\nThis typically means that you attempted to use functionality that\nneeded to interface with the current application object in some way.\nTo solve this, set up an application context with app.app_context().\n```\n\nExample:\n```text\ndef create_app():\n    app = Flask(__name__)\n\n    with app.app_context():\n        init_db()\n\n    return app\n```\n\nExample:\n```text\nfrom flask import g\n\ndef get_db():\n    if 'db' not in g:\n        g.db = connect_to_database()\n\n    return g.db\n\n@app.teardown_appcontext\ndef teardown_db(exception):\n    db = g.pop('db', None)\n\n    if db is not None:\n        db.close()\n```\n\nExample:\n```text\nfrom werkzeug.local import LocalProxy\ndb = LocalProxy(get_db)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.056Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":47,"estimatedTokens":1311}}33{"id":"doc-test_coverage_flask_documentation_3_1_x-488605b7","source":"documentation","title":"Test Coverage — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/tutorial/tests/","text":"Example:\n```text\n$ pip install pytest coverage\n```\n\nExample:\n```text\nINSERT INTO user (username, password)\nVALUES\n  ('test', 'pbkdf2:sha256:50000$TCI4GzcX$0de171a4f4dac32e3364c7ddc7c14f3e2fa61f2d17574483f7ffbb431b4acb2f'),\n  ('other', 'pbkdf2:sha256:50000$kJPKsz6N$d2d4784f1b030a9761f5ccaeeaca413f27f2ecb76d6168407af962ddce849f79');\n\nINSERT INTO post (title, body, author_id, created)\nVALUES\n  ('test title', 'test' || x'0a' || 'body', 1, '2018-01-01 00:00:00');\n```\n\nExample:\n```text\nimport os\nimport tempfile\n\nimport pytest\nfrom flaskr import create_app\nfrom flaskr.db import get_db, init_db\n\nwith open(os.path.join(os.path.dirname(__file__), 'data.sql'), 'rb') as f:\n    _data_sql = f.read().decode('utf8')\n\n\n@pytest.fixture\ndef app():\n    db_fd, db_path = tempfile.mkstemp()\n\n    app = create_app({\n        'TESTING': True,\n        'DATABASE': db_path,\n    })\n\n    with app.app_context():\n        init_db()\n        get_db().executescript(_data_sql)\n\n    yield app\n\n    os.close(db_fd)\n    os.unlink(db_path)\n\n\n@pytest.fixture\ndef client(app):\n    return app.test_client()\n\n\n@pytest.fixture\ndef runner(app):\n    return app.test_cli_runner()\n```\n\nExample:\n```text\nfrom flaskr import create_app\n\n\ndef test_config():\n    assert not create_app().testing\n    assert create_app({'TESTING': True}).testing\n\n\ndef test_hello(client):\n    response = client.get('/hello')\n    assert response.data == b'Hello, World!'\n```\n\nExample:\n```text\nimport sqlite3\n\nimport pytest\nfrom flaskr.db import get_db\n\n\ndef test_get_close_db(app):\n    with app.app_context():\n        db = get_db()\n        assert db is get_db()\n\n    with pytest.raises(sqlite3.ProgrammingError) as e:\n        db.execute('SELECT 1')\n\n    assert 'closed' in str(e.value)\n```\n\nExample:\n```text\ndef test_init_db_command(runner, monkeypatch):\n    class Recorder(object):\n        called = False\n\n    def fake_init_db():\n        Recorder.called = True\n\n    monkeypatch.setattr('flaskr.db.init_db', fake_init_db)\n    result = runner.invoke(args=['init-db'])\n    assert 'Initialized' in result.output\n    assert Recorder.called\n```\n\nExample:\n```text\nclass AuthActions(object):\n    def __init__(self, client):\n        self._client = client\n\n    def login(self, username='test', password='test'):\n        return self._client.post(\n            '/auth/login',\n            data={'username': username, 'password': password}\n        )\n\n    def logout(self):\n        return self._client.get('/auth/logout')\n\n\n@pytest.fixture\ndef auth(client):\n    return AuthActions(client)\n```\n\nExample:\n```text\nimport pytest\nfrom flask import g, session\nfrom flaskr.db import get_db\n\n\ndef test_register(client, app):\n    assert client.get('/auth/register').status_code == 200\n    response = client.post(\n        '/auth/register', data={'username': 'a', 'password': 'a'}\n    )\n    assert response.headers[\"Location\"] == \"/auth/login\"\n\n    with app.app_context():\n        assert get_db().execute(\n            \"SELECT * FROM user WHERE username = 'a'\",\n        ).fetchone() is not None\n\n\n@pytest.mark.parametrize(('username', 'password', 'message'), (\n    ('', '', b'Username is required.'),\n    ('a', '', b'Password is required.'),\n    ('test', 'test', b'already registered'),\n))\ndef test_register_validate_input(client, username, password, message):\n    response = client.post(\n        '/auth/register',\n        data={'username': username, 'password': password}\n    )\n    assert message in response.data\n```\n\nExample:\n```text\ndef test_login(client, auth):\n    assert client.get('/auth/login').status_code == 200\n    response = auth.login()\n    assert response.headers[\"Location\"] == \"/\"\n\n    with client:\n        client.get('/')\n        assert session['user_id'] == 1\n        assert g.user['username'] == 'test'\n\n\n@pytest.mark.parametrize(('username', 'password', 'message'), (\n    ('a', 'test', b'Incorrect username.'),\n    ('test', 'a', b'Incorrect password.'),\n))\ndef test_login_validate_input(auth, username, password, message):\n    response = auth.login(username, password)\n    assert message in response.data\n```\n\nExample:\n```text\ndef test_logout(client, auth):\n    auth.login()\n\n    with client:\n        auth.logout()\n        assert 'user_id' not in session\n```\n\nExample:\n```text\nimport pytest\nfrom flaskr.db import get_db\n\n\ndef test_index(client, auth):\n    response = client.get('/')\n    assert b\"Log In\" in response.data\n    assert b\"Register\" in response.data\n\n    auth.login()\n    response = client.get('/')\n    assert b'Log Out' in response.data\n    assert b'test title' in response.data\n    assert b'by test on 2018-01-01' in response.data\n    assert b'test\\nbody' in response.data\n    assert b'href=\"/1/update\"' in response.data\n```\n\nExample:\n```text\n@pytest.mark.parametrize('path', (\n    '/create',\n    '/1/update',\n    '/1/delete',\n))\ndef test_login_required(client, path):\n    response = client.post(path)\n    assert response.headers[\"Location\"] == \"/auth/login\"\n\n\ndef test_author_required(app, client, auth):\n    # change the post author to another user\n    with app.app_context():\n        db = get_db()\n        db.execute('UPDATE post SET author_id = 2 WHERE id = 1')\n        db.commit()\n\n    auth.login()\n    # current user can't modify other user's post\n    assert client.post('/1/update').status_code == 403\n    assert client.post('/1/delete').status_code == 403\n    # current user doesn't see edit link\n    assert b'href=\"/1/update\"' not in client.get('/').data\n\n\n@pytest.mark.parametrize('path', (\n    '/2/update',\n    '/2/delete',\n))\ndef test_exists_required(client, auth, path):\n    auth.login()\n    assert client.post(path).status_code == 404\n```\n\nExample:\n```text\ndef test_create(client, auth, app):\n    auth.login()\n    assert client.get('/create').status_code == 200\n    client.post('/create', data={'title': 'created', 'body': ''})\n\n    with app.app_context():\n        db = get_db()\n        count = db.execute('SELECT COUNT(id) FROM post').fetchone()[0]\n        assert count == 2\n\n\ndef test_update(client, auth, app):\n    auth.login()\n    assert client.get('/1/update').status_code == 200\n    client.post('/1/update', data={'title': 'updated', 'body': ''})\n\n    with app.app_context():\n        db = get_db()\n        post = db.execute('SELECT * FROM post WHERE id = 1').fetchone()\n        assert post['title'] == 'updated'\n\n\n@pytest.mark.parametrize('path', (\n    '/create',\n    '/1/update',\n))\ndef test_create_update_validate(client, auth, path):\n    auth.login()\n    response = client.post(path, data={'title': '', 'body': ''})\n    assert b'Title is required.' in response.data\n```\n\nExample:\n```text\ndef test_delete(client, auth, app):\n    auth.login()\n    response = client.post('/1/delete')\n    assert response.headers[\"Location\"] == \"/\"\n\n    with app.app_context():\n        db = get_db()\n        post = db.execute('SELECT * FROM post WHERE id = 1').fetchone()\n        assert post is None\n```\n\nExample:\n```text\n[tool.pytest.ini_options]\ntestpaths = [\"tests\"]\n\n[tool.coverage.run]\nbranch = true\nsource = [\"flaskr\"]\n```\n\nExample:\n```text\n$ pytest\n\n========================= test session starts ==========================\nplatform linux -- Python 3.6.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0\nrootdir: /home/user/Projects/flask-tutorial\ncollected 23 items\n\ntests/test_auth.py ........                                      [ 34%]\ntests/test_blog.py ............                                  [ 86%]\ntests/test_db.py ..                                              [ 95%]\ntests/test_factory.py ..                                         [100%]\n\n====================== 24 passed in 0.64 seconds =======================\n```\n\nExample:\n```text\n$ coverage run -m pytest\n```\n\nExample:\n```text\n$ coverage report\n\nName                 Stmts   Miss Branch BrPart  Cover\n------------------------------------------------------\nflaskr/__init__.py      21      0      2      0   100%\nflaskr/auth.py          54      0     22      0   100%\nflaskr/blog.py          54      0     16      0   100%\nflaskr/db.py            24      0      4      0   100%\n------------------------------------------------------\nTOTAL                  153      0     44      0   100%\n```\n\nExample:\n```text\n$ coverage html\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.057Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":19,"totalLines":349,"estimatedTokens":2039}}34{"id":"doc-the_request_context_flask_documentation_3_1_x-0831c0ae","source":"documentation","title":"The Request Context — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/reqcontext/","text":"The Request Context¶ The request context keeps track of the request-level data during a request. Rather than passing the request object to each function that runs during a request, the request and session proxies are accessed instead. This is similar to The Application Context, which keeps track of the application-level data independent of a request. A corresponding application context is pushed when a request context is pushed. Purpose of the Context¶ When the Flask application handles a request, it creates a Request object based on the environment it received from the WSGI server. Because a worker (thread, process, or coroutine depending on the server) handles only one request at a time, the request data can be considered global to that worker during that request. Flask uses the term context local for this. Flask automatically pushes a request context when handling a request. View functions, error handlers, and other functions that run during a request will have access to the request proxy, which points to the request object for the current request. Lifetime of the Context¶ When a Flask application begins handling a request, it pushes a request context, which also pushes an app context. When the request ends it pops the request context then the application context. The context is unique to each thread (or other worker type). request cannot be passed to another thread, the other thread has a different context space and will not know about the request the parent thread was pointing to. Context locals are implemented using Python’s contextvars and Werkzeug’s LocalProxy. Python manages the lifetime of context vars automatically, and local proxy wraps that low-level interface to make the data easier to work with. Manually Push a Context¶ If you try to access request, or anything that uses it, outside a request context, you’ll get this error : Working outside of request context. This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem. This should typically only happen when testing code that expects an active request. One option is to use the test client to simulate a full request. Or you can use test_request_context() in a with block, and everything that runs in the block will have access to request, populated with your test data. def generate_report(year): format = request.args.get(\"format\") ... with app.test_request_context( \"/make_report/2017\", query_string={\"format\": \"short\"} ): generate_report() If you see that error somewhere else in your code not related to testing, it most likely indicates that you should move that code into a view function. For information on how to use the request context from the interactive Python shell, see Working with the Shell. How the Context Works¶ The Flask.wsgi_app() method is called to handle each request. It manages the contexts during the request. Internally, the request and application contexts work like stacks. When contexts are pushed, the proxies that depend on them are available and point at information from the top item. When the request starts, a RequestContext is created and pushed, which creates and pushes an AppContext first if a context for that application is not already the top context. While these contexts are pushed, the current_app, g, request, and session proxies are available to the original thread handling the request. Other contexts may be pushed to change the proxies during a request. While this is not a common pattern, it can be used in advanced applications to, for example, do internal redirects or chain different applications together. After the request is dispatched and a response is generated and sent, the request context is popped, which then pops the application context. Immediately before they are popped, the teardown_request() and teardown_appcontext() functions are executed. These execute even if an unhandled exception occurred during dispatch. Callbacks and Errors¶ Flask dispatches a request in multiple stages which can affect the request, response, and how errors are handled. The contexts are active during all of these stages. A Blueprint can add handlers for these events that are specific to the blueprint. The handlers for a blueprint will run if the blueprint owns the route that matches the request. Before each request, before_request() functions are called. If one of these functions return a value, the other functions are skipped. The return value is treated as the response and the view function is not called. If the before_request() functions did not return a response, the view function for the matched route is called and returns a response. The return value of the view is converted into an actual response object and passed to the after_request() functions. Each function returns a modified or new response object. After the response is returned, the contexts are popped, which calls the teardown_request() and teardown_appcontext() functions. These functions are called even if an unhandled exception was raised at any point above. If an exception is raised before the teardown functions, Flask tries to match it with an errorhandler() function to handle the exception and return a response. If no error handler is found, or the handler itself raises an exception, Flask returns a generic 500 Internal Server Error response. The teardown functions are still called, and are passed the exception object. If debug mode is enabled, unhandled exceptions are not converted to a 500 response and instead are propagated to the WSGI server. This allows the development server to present the interactive debugger with the traceback. Teardown Callbacks¶ The teardown callbacks are independent of the request dispatch, and are instead called by the contexts when they are popped. The functions are called even if there is an unhandled exception during dispatch, and for manually pushed contexts. This means there is no guarantee that any other parts of the request dispatch have run first. Be sure to write these functions in a way that does not depend on other callbacks and will not fail. During testing, it can be useful to defer popping the contexts after the request ends, so that their data can be accessed in the test function. Use the test_client() as a with block to preserve the contexts until the with block exits. from flask import Flask, request app = Flask(__name__) @app.route('/') def hello(): print('during view') return 'Hello, World!' @app.teardown_request def show_teardown(exception): print('after with block') with app.test_request_context(): print('during with block') # teardown functions are called after the context with block exits with app.test_client() as ('/') # the contexts are not popped even though the request ended print(request.path) # the contexts are popped and teardown functions are called after # the client with block exits Signals¶ The following signals are is sent before the before_request() functions are called. request_finished is sent after the after_request() functions are called. got_request_exception is sent when an exception begins to be handled, but before an errorhandler() is looked up or called. request_tearing_down is sent after the teardown_request() functions are called. Notes On Proxies¶ Some of the objects provided by Flask are proxies to other objects. The proxies are accessed in the same way for each worker thread, but point to the unique object bound to each worker behind the scenes as described on this page. Most of the time you don’t have to care about that, but there are some exceptions where it is good to know that this object is actually a proxy objects cannot fake their type as the actual object types. If you want to perform instance checks, you have to do that on the object being proxied. The reference to the proxied object is needed in some situations, such as sending Signals or passing data to a background thread. If you need to access the underlying object that is proxied, use the _get_current_object() = current_app._get_current_object() my_signal.send(app) Contents The Request Context Purpose of the Context Lifetime of the Context Manually Push a Context How the Context Works Callbacks and Errors Teardown Callbacks Signals Notes On Proxies Navigation Overview Application Context Applications with Blueprints Quick search\n\nExample:\n```text\nRuntimeError: Working outside of request context.\n\nThis typically means that you attempted to use functionality that\nneeded an active HTTP request. Consult the documentation on testing\nfor information about how to avoid this problem.\n```\n\nExample:\n```text\ndef generate_report(year):\n    format = request.args.get(\"format\")\n    ...\n\nwith app.test_request_context(\n    \"/make_report/2017\", query_string={\"format\": \"short\"}\n):\n    generate_report()\n```\n\nExample:\n```text\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.route('/')\ndef hello():\n    print('during view')\n    return 'Hello, World!'\n\n@app.teardown_request\ndef show_teardown(exception):\n    print('after with block')\n\nwith app.test_request_context():\n    print('during with block')\n\n# teardown functions are called after the context with block exits\n\nwith app.test_client() as client:\n    client.get('/')\n    # the contexts are not popped even though the request ended\n    print(request.path)\n\n# the contexts are popped and teardown functions are called after\n# the client with block exits\n```\n\nExample:\n```text\napp = current_app._get_current_object()\nmy_signal.send(app)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.059Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":59,"estimatedTokens":2394}}35{"id":"doc-quickstart_flask_documentation_3_1_x-0decb90a","source":"documentation","title":"Quickstart — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/quickstart/","text":"Example:\n```text\nfrom flask import Flask\n\napp = Flask(__name__)\n\n@app.route(\"/\")\ndef hello_world():\n    return \"<p>Hello, World!</p>\"\n```\n\nExample:\n```text\n$ flask --app hello run\n * Serving Flask app 'hello'\n * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)\n```\n\nExample:\n```text\n$ flask run --host=0.0.0.0\n```\n\nExample:\n```text\n$ flask --app hello run --debug\n * Serving Flask app 'hello'\n * Debug mode: on\n * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)\n * Restarting with stat\n * Debugger is active!\n * Debugger PIN: nnn-nnn-nnn\n```\n\nExample:\n```text\nfrom flask import request\nfrom markupsafe import escape\n\n@app.route(\"/hello\")\ndef hello():\n    name = request.args.get(\"name\", \"Flask\")\n    return f\"Hello, {escape(name)}!\"\n```\n\nExample:\n```text\n@app.route('/')\ndef index():\n    return 'Index Page'\n\n@app.route('/hello')\ndef hello():\n    return 'Hello, World'\n```\n\nExample:\n```text\nfrom markupsafe import escape\n\n@app.route('/user/<username>')\ndef show_user_profile(username):\n    # show the user profile for that user\n    return f'User {escape(username)}'\n\n@app.route('/post/<int:post_id>')\ndef show_post(post_id):\n    # show the post with the given id, the id is an integer\n    return f'Post {post_id}'\n\n@app.route('/path/<path:subpath>')\ndef show_subpath(subpath):\n    # show the subpath after /path/\n    return f'Subpath {escape(subpath)}'\n```\n\nExample:\n```text\n@app.route('/projects/')\ndef projects():\n    return 'The project page'\n\n@app.route('/about')\ndef about():\n    return 'The about page'\n```\n\nExample:\n```text\nfrom flask import url_for\n\n@app.route('/')\ndef index():\n    return 'index'\n\n@app.route('/login')\ndef login():\n    return 'login'\n\n@app.route('/user/<username>')\ndef profile(username):\n    return f'{username}\\'s profile'\n\nwith app.test_request_context():\n    print(url_for('index'))\n    print(url_for('login'))\n    print(url_for('login', next='/'))\n    print(url_for('profile', username='John Doe'))\n```\n\nExample:\n```text\n/\n/login\n/login?next=/\n/user/John%20Doe\n```\n\nExample:\n```text\nfrom flask import request\n\n@app.route('/login', methods=['GET', 'POST'])\ndef login():\n    if request.method == 'POST':\n        return do_the_login()\n    else:\n        return show_the_login_form()\n```\n\nExample:\n```text\n@app.get('/login')\ndef login_get():\n    return show_the_login_form()\n\n@app.post('/login')\ndef login_post():\n    return do_the_login()\n```\n\nExample:\n```text\nurl_for('static', filename='style.css')\n```\n\nExample:\n```text\nfrom flask import render_template\n\n@app.route('/hello/')\n@app.route('/hello/<name>')\ndef hello(name=None):\n    return render_template('hello.html', person=name)\n```\n\nExample:\n```text\n/application.py\n/templates\n    /hello.html\n```\n\nExample:\n```text\n/application\n    /__init__.py\n    /templates\n        /hello.html\n```\n\nExample:\n```text\n<!doctype html>\n<title>Hello from Flask</title>\n{% if person %}\n  <h1>Hello {{ person }}!</h1>\n{% else %}\n  <h1>Hello, World!</h1>\n{% endif %}\n```\n\nExample:\n```text\n>>> from markupsafe import Markup\n>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'\nMarkup('<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')\n>>> Markup.escape('<blink>hacker</blink>')\nMarkup('&lt;blink&gt;hacker&lt;/blink&gt;')\n>>> Markup('<em>Marked up</em> &raquo; HTML').striptags()\n'Marked up » HTML'\n```\n\nExample:\n```text\nfrom flask import request\n\nwith app.test_request_context('/hello', method='POST'):\n    # now you can do something with the request until the\n    # end of the with block, such as basic assertions:\n    assert request.path == '/hello'\n    assert request.method == 'POST'\n```\n\nExample:\n```text\nwith app.request_context(environ):\n    assert request.method == 'POST'\n```\n\nExample:\n```text\nfrom flask import request\n```\n\nExample:\n```text\n@app.route('/login', methods=['POST', 'GET'])\ndef login():\n    error = None\n    if request.method == 'POST':\n        if valid_login(request.form['username'],\n                       request.form['password']):\n            return log_the_user_in(request.form['username'])\n        else:\n            error = 'Invalid username/password'\n    # the code below is executed if the request method\n    # was GET or the credentials were invalid\n    return render_template('login.html', error=error)\n```\n\nExample:\n```text\nsearchword = request.args.get('key', '')\n```\n\nExample:\n```text\nfrom flask import request\n\n@app.route('/upload', methods=['GET', 'POST'])\ndef upload_file():\n    if request.method == 'POST':\n        f = request.files['the_file']\n        f.save('/var/www/uploads/uploaded_file.txt')\n    ...\n```\n\nExample:\n```text\nfrom werkzeug.utils import secure_filename\n\n@app.route('/upload', methods=['GET', 'POST'])\ndef upload_file():\n    if request.method == 'POST':\n        file = request.files['the_file']\n        file.save(f\"/var/www/uploads/{secure_filename(file.filename)}\")\n    ...\n```\n\nExample:\n```text\nfrom flask import request\n\n@app.route('/')\ndef index():\n    username = request.cookies.get('username')\n    # use cookies.get(key) instead of cookies[key] to not get a\n    # KeyError if the cookie is missing.\n```\n\nExample:\n```text\nfrom flask import make_response\n\n@app.route('/')\ndef index():\n    resp = make_response(render_template(...))\n    resp.set_cookie('username', 'the username')\n    return resp\n```\n\nExample:\n```text\nfrom flask import abort, redirect, url_for\n\n@app.route('/')\ndef index():\n    return redirect(url_for('login'))\n\n@app.route('/login')\ndef login():\n    abort(401)\n    this_is_never_executed()\n```\n\nExample:\n```text\nfrom flask import render_template\n\n@app.errorhandler(404)\ndef page_not_found(error):\n    return render_template('page_not_found.html'), 404\n```\n\nExample:\n```text\nfrom flask import render_template\n\n@app.errorhandler(404)\ndef not_found(error):\n    return render_template('error.html'), 404\n```\n\nExample:\n```text\nfrom flask import make_response\n\n@app.errorhandler(404)\ndef not_found(error):\n    resp = make_response(render_template('error.html'), 404)\n    resp.headers['X-Something'] = 'A value'\n    return resp\n```\n\nExample:\n```text\n@app.route(\"/me\")\ndef me_api():\n    user = get_current_user()\n    return {\n        \"username\": user.username,\n        \"theme\": user.theme,\n        \"image\": url_for(\"user_image\", filename=user.image),\n    }\n\n@app.route(\"/users\")\ndef users_api():\n    users = get_all_users()\n    return [user.to_json() for user in users]\n```\n\nExample:\n```text\nfrom flask import session\n\n# Set the secret key to some random bytes. Keep this really secret!\napp.secret_key = b'_5#y2L\"F4Q8z\\n\\xec]/'\n\n@app.route('/')\ndef index():\n    if 'username' in session:\n        return f'Logged in as {session[\"username\"]}'\n    return 'You are not logged in'\n\n@app.route('/login', methods=['GET', 'POST'])\ndef login():\n    if request.method == 'POST':\n        session['username'] = request.form['username']\n        return redirect(url_for('index'))\n    return '''\n        <form method=\"post\">\n            <p><input type=text name=username>\n            <p><input type=submit value=Login>\n        </form>\n    '''\n\n@app.route('/logout')\ndef logout():\n    # remove the username from the session if it's there\n    session.pop('username', None)\n    return redirect(url_for('index'))\n```\n\nExample:\n```text\n$ python -c 'import secrets; print(secrets.token_hex())'\n'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'\n```\n\nExample:\n```text\napp.logger.debug('A value for debugging')\napp.logger.warning('A warning occurred (%d apples)', 42)\napp.logger.error('An error occurred')\n```\n\nExample:\n```text\nfrom werkzeug.middleware.proxy_fix import ProxyFix\napp.wsgi_app = ProxyFix(app.wsgi_app)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.061Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":36,"totalLines":394,"estimatedTokens":1900}}36{"id":"doc-templates_flask_documentation_3_1_x-dba6b6d1","source":"documentation","title":"Templates — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/templating/","text":"Templates¶ Flask leverages Jinja as its template engine. You are obviously free to use a different template engine, but you still have to install Jinja to run Flask itself. This requirement is necessary to enable rich extensions. An extension can depend on Jinja being present. This section only gives a very quick introduction into how Jinja is integrated into Flask. If you want information on the template engine’s syntax itself, head over to the official Jinja Template Documentation for more information. Jinja Setup¶ Unless customized, Jinja is configured by Flask as is enabled for all templates ending in tag. Flask inserts a couple of global functions and helpers into the Jinja context, additionally to the values that are present by default. Standard Context¶ The following global variables are available within Jinja templates by The current configuration object (flask.Flask.config) Changelog Changed in version 0.10: This is now always available, even in imported templates. Added in version 0.6. request The current request object (flask.request). This variable is unavailable if the template was rendered without an active request context. session The current session object (flask.session). This variable is unavailable if the template was rendered without an active request context. g The request-bound object for global variables (flask.g). This variable is unavailable if the template was rendered without an active request context. url_for() The flask.url_for() function. get_flashed_messages() The flask.get_flashed_messages() function. The Jinja Context Behavior These variables are added to the context of variables, they are not global variables. The difference is that by default these will not show up in the context of imported templates. This is partially caused by performance considerations, partially to keep things explicit. What does this mean for you? If you have a macro you want to import, that needs to access the request object you have two explicitly pass the request to the macro as parameter, or the attribute of the request object you are interested in. you import the macro “with context”. Importing with context looks like this: {% from '_helpers.html' import my_macro with context %} Controlling Autoescaping¶ Autoescaping is the concept of automatically escaping special characters for you. Special characters in the sense of HTML (or XML, and thus XHTML) are &, >, <, \" as well as '. Because these characters carry specific meanings in documents on their own you have to replace them by so called “entities” if you want to use them for text. Not doing so would not only cause user frustration by the inability to use these characters in text, but can also lead to security problems. (see Cross-Site Scripting (XSS)) Sometimes however you will need to disable autoescaping in templates. This can be the case if you want to explicitly inject HTML into pages, for example if they come from a system that generates secure HTML like a markdown to HTML converter. There are three ways to accomplish the Python code, wrap the HTML string in a Markup object before passing it to the template. This is in general the recommended way. Inside the template, use the |safe filter to explicitly mark a string as safe HTML ({{ myvariable|safe }}) Temporarily disable the autoescape system altogether. To disable the autoescape system in templates, you can use the {% autoescape %} block: {% autoescape false %} <p>autoescaping is disabled here <p>{{ will_not_be_escaped }} {% endautoescape %} Whenever you do this, please be very cautious about the variables you are using in this block. Registering Filters¶ If you want to register your own filters in Jinja you have two ways to do that. You can either put them by hand into the jinja_env of the application or use the template_filter() decorator. The two following examples work the same and both reverse an object: @app.template_filter('reverse') def reverse_filter(s): return s[::-1] def reverse_filter(s): return s[::-1] app.jinja_env.filters['reverse'] = reverse_filter In case of the decorator the argument is optional if you want to use the function name as name of the filter. Once registered, you can use the filter in your templates in the same way as Jinja’s builtin filters, for example if you have a Python list in context called mylist: {% for x in mylist | reverse %} {% endfor %} Context Processors¶ To inject new variables automatically into the context of a template, context processors exist in Flask. Context processors run before the template is rendered and have the ability to inject new values into the template context. A context processor is a function that returns a dictionary. The keys and values of this dictionary are then merged with the template context, for all templates in the app: @app.context_processor def inject_user(): return dict(user=g.user) The context processor above makes a variable called user available in the template with the value of g.user. This example is not very interesting because g is available in templates anyways, but it gives an idea how this works. Variables are not limited to values; a context processor can also make functions available to templates (since Python allows passing around functions): @app.context_processor def utility_processor(): def format_price(amount, currency=\"€\"): return f\"{amount:.2f}{currency}\" return dict(format_price=format_price) The context processor above makes the format_price function available to all templates: {{ format_price(0.33) }} You could also build format_price as a template filter (see Registering Filters), but this demonstrates how to pass functions in a context processor. Streaming¶ It can be useful to not render the whole template as one complete string, instead render it as a stream, yielding smaller incremental strings. This can be used for streaming HTML in chunks to speed up initial page load, or to save memory when rendering a very large template. The Jinja template engine supports rendering a template piece by piece, returning an iterator of strings. Flask provides the stream_template() and stream_template_string() functions to make this easier to use. from flask import stream_template @app.get(\"/timeline\") def timeline(): return stream_template(\"timeline.html\") These functions automatically apply the stream_with_context() wrapper if a request is active, so that request, session, and g remain available in the template. More headers cannot be sent after the body has begun. Therefore, you must make sure all headers are set before starting the response. In particular, if the template will access session, be sure to do so in the view as well so that the header will be set. Contents Templates Jinja Setup Standard Context Controlling Autoescaping Registering Filters Context Processors Streaming Navigation Overview Developing! Flask Applications Quick search\n\nExample:\n```text\n{% from '_helpers.html' import my_macro with context %}\n```\n\nExample:\n```text\n{% autoescape false %}\n    <p>autoescaping is disabled here\n    <p>{{ will_not_be_escaped }}\n{% endautoescape %}\n```\n\nExample:\n```text\n@app.template_filter('reverse')\ndef reverse_filter(s):\n    return s[::-1]\n\ndef reverse_filter(s):\n    return s[::-1]\napp.jinja_env.filters['reverse'] = reverse_filter\n```\n\nExample:\n```text\n{% for x in mylist | reverse %}\n{% endfor %}\n```\n\nExample:\n```text\n@app.context_processor\ndef inject_user():\n    return dict(user=g.user)\n```\n\nExample:\n```text\n@app.context_processor\ndef utility_processor():\n    def format_price(amount, currency=\"€\"):\n        return f\"{amount:.2f}{currency}\"\n    return dict(format_price=format_price)\n```\n\nExample:\n```text\n{{ format_price(0.33) }}\n```\n\nExample:\n```text\nfrom flask import stream_template\n\n@app.get(\"/timeline\")\ndef timeline():\n    return stream_template(\"timeline.html\")\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.062Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":8,"totalLines":63,"estimatedTokens":1961}}37{"id":"doc-logging_flask_documentation_3_1_x-ea9592df","source":"documentation","title":"Logging — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/logging/","text":"Example:\n```text\n@app.route('/login', methods=['POST'])\ndef login():\n    user = get_user(request.form['username'])\n\n    if user.check_password(request.form['password']):\n        login_user(user)\n        app.logger.info('%s logged in successfully', user.username)\n        return redirect(url_for('index'))\n    else:\n        app.logger.info('%s failed to log in', user.username)\n        abort(401)\n```\n\nExample:\n```text\nfrom logging.config import dictConfig\n\ndictConfig({\n    'version': 1,\n    'formatters': {'default': {\n        'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',\n    }},\n    'handlers': {'wsgi': {\n        'class': 'logging.StreamHandler',\n        'stream': 'ext://flask.logging.wsgi_errors_stream',\n        'formatter': 'default'\n    }},\n    'root': {\n        'level': 'INFO',\n        'handlers': ['wsgi']\n    }\n})\n\napp = Flask(__name__)\n```\n\nExample:\n```text\nfrom flask.logging import default_handler\n\napp.logger.removeHandler(default_handler)\n```\n\nExample:\n```text\nimport logging\nfrom logging.handlers import SMTPHandler\n\nmail_handler = SMTPHandler(\n    mailhost='127.0.0.1',\n    fromaddr='server-error@example.com',\n    toaddrs=['admin@example.com'],\n    subject='Application Error'\n)\nmail_handler.setLevel(logging.ERROR)\nmail_handler.setFormatter(logging.Formatter(\n    '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'\n))\n\nif not app.debug:\n    app.logger.addHandler(mail_handler)\n```\n\nExample:\n```text\nfrom flask import has_request_context, request\nfrom flask.logging import default_handler\n\nclass RequestFormatter(logging.Formatter):\n    def format(self, record):\n        if has_request_context():\n            record.url = request.url\n            record.remote_addr = request.remote_addr\n        else:\n            record.url = None\n            record.remote_addr = None\n\n        return super().format(record)\n\nformatter = RequestFormatter(\n    '[%(asctime)s] %(remote_addr)s requested %(url)s\\n'\n    '%(levelname)s in %(module)s: %(message)s'\n)\ndefault_handler.setFormatter(formatter)\nmail_handler.setFormatter(formatter)\n```\n\nExample:\n```text\nfrom flask.logging import default_handler\n\nroot = logging.getLogger()\nroot.addHandler(default_handler)\nroot.addHandler(mail_handler)\n```\n\nExample:\n```text\nfor logger in (\n    logging.getLogger(app.name),\n    logging.getLogger('sqlalchemy'),\n    logging.getLogger('other_package'),\n):\n    logger.addHandler(default_handler)\n    logger.addHandler(mail_handler)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.062Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":110,"estimatedTokens":617}}38{"id":"doc-application_structure_and_lifecycle_flask_docume-58d28ffe","source":"documentation","title":"Application Structure and Lifecycle — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/lifecycle/","text":"Application Structure and Lifecycle¶ Flask makes it pretty easy to write a web application. But there are quite a few different parts to an application and to each request it handles. Knowing what happens during application setup, serving, and handling requests will help you know what’s possible in Flask and how to structure your application. Application Setup¶ The first step in creating a Flask application is creating the application object. Each Flask application is an instance of the Flask class, which collects all configuration, extensions, and views. from flask import Flask app = Flask(__name__) app.config.from_mapping( SECRET_KEY=\"dev\", ) app.config.from_prefixed_env() @app.route(\"/\") def index(): return \"Hello, World!\" This is known as the “application setup phase”, it’s the code you write that’s outside any view functions or other handlers. It can be split up between different modules and sub-packages, but all code that you want to be part of your application must be imported in order for it to be registered. All application setup must be completed before you start serving your application and handling requests. This is because WSGI servers divide work between multiple workers, or can be distributed across multiple machines. If the configuration changed in one worker, there’s no way for Flask to ensure consistency between other workers. Flask tries to help developers catch some of these setup ordering issues by showing an error if setup-related methods are called after requests are handled. In that case you’ll see this setup method ‘route’ can no longer be called on the application. It has already handled its first request, any changes will not be applied consistently. Make sure all imports, decorators, functions, etc. needed to set up the application are done before running it. However, it is not possible for Flask to detect all cases of out-of-order setup. In general, don’t do anything to modify the Flask app object and Blueprint objects from within view functions that run during requests. This routes, view functions, and other request handlers with @app.route, @app.errorhandler, @app.before_request, etc. Registering blueprints. Loading configuration with app.config. Setting up the Jinja template environment with app.jinja_env. Setting a session interface, instead of the default itsdangerous cookie. Setting a JSON provider with app.json, instead of the default provider. Creating and initializing Flask extensions. Serving the Application¶ Flask is a WSGI application framework. The other half of WSGI is the WSGI server. During development, Flask, through Werkzeug, provides a development WSGI server with the flask run CLI command. When you are done with development, use a production server to serve your application, see Deploying to Production. Regardless of what server you’re using, it will follow the PEP 3333 WSGI spec. The WSGI server will be told how to access your Flask application object, which is the WSGI application. Then it will start listening for HTTP requests, translate the request data into a WSGI environ, and call the WSGI application with that data. The WSGI application will return data that is translated into an HTTP response. Browser or other client makes HTTP request. WSGI server receives request. WSGI server converts HTTP data to WSGI environ dict. WSGI server calls WSGI application with the environ. Flask, the WSGI application, does all its internal processing to route the request to a view function, handle errors, etc. Flask translates View function return into WSGI response data, passes it to WSGI server. WSGI server creates and send an HTTP response. Client receives the HTTP response. Middleware¶ The WSGI application above is a callable that behaves in a certain way. Middleware is a WSGI application that wraps another WSGI application. It’s a similar concept to Python decorators. The outermost middleware will be called by the server. It can modify the data passed to it, then call the WSGI application (or further middleware) that it wraps, and so on. And it can take the return value of that call and modify it further. From the WSGI server’s perspective, there is one WSGI application, the one it calls directly. Typically, Flask is the “real” application at the end of the chain of middleware. But even Flask can call further WSGI applications, although that’s an advanced, uncommon use case. A common middleware you’ll see used with Flask is Werkzeug’s ProxyFix, which modifies the request to look like it came directly from a client even if it passed through HTTP proxies on the way. There are other middleware that can handle serving static files, authentication, etc. How a Request is Handled¶ For us, the interesting part of the steps above is when Flask gets called by the WSGI server (or middleware). At that point, it will do quite a lot to handle the request and generate the response. At the most basic, it will match the URL to a view function, call the view function, and pass the return value back to the server. But there are many more parts that you can use to customize its behavior. WSGI server calls the Flask object, which calls Flask.wsgi_app(). A RequestContext object is created. This converts the WSGI environ dict into a Request object. It also creates an AppContext object. The app context is pushed, which makes current_app and g available. The appcontext_pushed signal is sent. The request context is pushed, which makes request and session available. The session is opened, loading any existing session data using the app’s session_interface, an instance of SessionInterface. The URL is matched against the URL rules registered with the route() decorator during application setup. If there is no match, the error - usually a 404, 405, or redirect - is stored to be handled later. The request_started signal is sent. Any url_value_preprocessor() decorated functions are called. Any before_request() decorated functions are called. If any of these function returns a value it is treated as the response immediately. If the URL didn’t match a route a few steps ago, that error is raised now. The route() decorated view function associated with the matched URL is called and returns a value to be used as the response. If any step so far raised an exception, and there is an errorhandler() decorated function that matches the exception class or HTTP error code, it is called to handle the error and return a response. Whatever returned a response value - a before request function, the view, or an error handler, that value is converted to a Response object. Any after_this_request() decorated functions are called, then cleared. Any after_request() decorated functions are called, which can modify the response object. The session is saved, persisting any modified session data using the app’s session_interface. The request_finished signal is sent. If any step so far raised an exception, and it was not handled by an error handler function, it is handled now. HTTP exceptions are treated as responses with their corresponding status code, other exceptions are converted to a generic 500 response. The got_request_exception signal is sent. The response object’s status, headers, and body are returned to the WSGI server. Any teardown_request() decorated functions are called. The request_tearing_down signal is sent. The request context is popped, request and session are no longer available. Any teardown_appcontext() decorated functions are called. The appcontext_tearing_down signal is sent. The app context is popped, current_app and g are no longer available. The appcontext_popped signal is sent. There are even more decorators and customization points than this, but that aren’t part of every request lifecycle. They’re more specific to certain things you might use during a request, such as templates, building URLs, or handling JSON data. See the rest of this documentation, as well as the API to explore further. Contents Application Structure and Lifecycle Application Setup Serving the Application Middleware How a Request is Handled Navigation Overview Views Application Context Quick search\n\nExample:\n```text\nfrom flask import Flask\n\napp = Flask(__name__)\napp.config.from_mapping(\n    SECRET_KEY=\"dev\",\n)\napp.config.from_prefixed_env()\n\n@app.route(\"/\")\ndef index():\n    return \"Hello, World!\"\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.063Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":1,"totalLines":18,"estimatedTokens":2089}}39{"id":"doc-signals_flask_documentation_3_1_x-193c4a96","source":"documentation","title":"Signals — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/signals/","text":"Example:\n```text\nfrom flask import template_rendered\nfrom contextlib import contextmanager\n\n@contextmanager\ndef captured_templates(app):\n    recorded = []\n    def record(sender, template, context, **extra):\n        recorded.append((template, context))\n    template_rendered.connect(record, app)\n    try:\n        yield recorded\n    finally:\n        template_rendered.disconnect(record, app)\n```\n\nExample:\n```text\nwith captured_templates(app) as templates:\n    rv = app.test_client().get('/')\n    assert rv.status_code == 200\n    assert len(templates) == 1\n    template, context = templates[0]\n    assert template.name == 'index.html'\n    assert len(context['items']) == 10\n```\n\nExample:\n```text\nfrom flask import template_rendered\n\ndef captured_templates(app, recorded, **extra):\n    def record(sender, template, context):\n        recorded.append((template, context))\n    return template_rendered.connected_to(record, app)\n```\n\nExample:\n```text\ntemplates = []\nwith captured_templates(app, templates, **extra):\n    ...\n    template, context = templates[0]\n```\n\nExample:\n```text\nfrom blinker import Namespace\nmy_signals = Namespace()\n```\n\nExample:\n```text\nmodel_saved = my_signals.signal('model-saved')\n```\n\nExample:\n```text\nclass Model(object):\n    ...\n\n    def save(self):\n        model_saved.send(self)\n```\n\nExample:\n```text\nfrom flask import template_rendered\n\n@template_rendered.connect_via(app)\ndef when_template_rendered(sender, template, context, **extra):\n    print(f'Template {template.name} is rendered with {context}')\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.065Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":8,"totalLines":76,"estimatedTokens":387}}40{"id":"doc-modular_applications_with_blueprints_flask_docum-b1825e06","source":"documentation","title":"Modular Applications with Blueprints — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/blueprints/","text":"Modular Applications with Blueprints¶ Changelog Added in version 0.7. Flask uses a concept of blueprints for making application components and supporting common patterns within an application or across applications. Blueprints can greatly simplify how large applications work and provide a central means for Flask extensions to register operations on applications. A Blueprint object works similarly to a Flask application object, but it is not actually an application. Rather it is a blueprint of how to construct or extend an application. Why Blueprints?¶ Blueprints in Flask are intended for these an application into a set of blueprints. This is ideal for larger applications; a project could instantiate an application object, initialize several extensions, and register a collection of blueprints. Register a blueprint on an application at a URL prefix and/or subdomain. Parameters in the URL prefix/subdomain become common view arguments (with defaults) across all view functions in the blueprint. Register a blueprint multiple times on an application with different URL rules. Provide template filters, static files, templates, and other utilities through blueprints. A blueprint does not have to implement applications or view functions. Register a blueprint on an application for any of these cases when initializing a Flask extension. A blueprint in Flask is not a pluggable app because it is not actually an application – it’s a set of operations which can be registered on an application, even multiple times. Why not have multiple application objects? You can do that (see Application Dispatching), but your applications will have separate configs and will be managed at the WSGI layer. Blueprints instead provide separation at the Flask level, share application config, and can change an application object as necessary with being registered. The downside is that you cannot unregister a blueprint once an application was created without having to destroy the whole application object. The Concept of Blueprints¶ The basic concept of blueprints is that they record operations to execute when registered on an application. Flask associates view functions with blueprints when dispatching requests and generating URLs from one endpoint to another. My First Blueprint¶ This is what a very basic blueprint looks like. In this case we want to implement a blueprint that does simple rendering of static flask import Blueprint, render_template, abort from jinja2 import TemplateNotFound simple_page = Blueprint('simple_page', __name__, template_folder='templates') @simple_page.route('/', defaults={'page': 'index'}) @simple_page.route('/<page>') def show(page): render_template(f'pages/{page}.html') except (404) When you bind a function with the help of the @simple_page.route decorator, the blueprint will record the intention of registering the function show on the application when it’s later registered. Additionally it will prefix the endpoint of the function with the name of the blueprint which was given to the Blueprint constructor (in this case also simple_page). The blueprint’s name does not modify the URL, only the endpoint. Registering Blueprints¶ So how do you register that blueprint? Like flask import Flask from yourapplication.simple_page import simple_page app = Flask(__name__) app.register_blueprint(simple_page) If you check the rules registered on the application, you will find these: >>> app.url_map Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>, <Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>, <Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>]) The first one is obviously from the application itself for the static files. The other two are for the show function of the simple_page blueprint. As you can see, they are also prefixed with the name of the blueprint and separated by a dot (.). Blueprints however can also be mounted at different (simple_page, url_prefix='/pages') And sure enough, these are the generated rules: >>> app.url_map Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>, <Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>, <Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>]) On top of that you can register blueprints multiple times though not every blueprint might respond properly to that. In fact it depends on how the blueprint is implemented if it can be mounted more than once. Nesting Blueprints¶ It is possible to register a blueprint on another blueprint. parent = Blueprint('parent', __name__, url_prefix='/parent') child = Blueprint('child', __name__, url_prefix='/child') parent.register_blueprint(child) app.register_blueprint(parent) The child blueprint will gain the parent’s name as a prefix to its name, and child URLs will be prefixed with the parent’s URL prefix. url_for('parent.child.create') /parent/child/create In addition a child blueprint’s will gain their parent’s subdomain, with their subdomain as prefix if present i.e. parent = Blueprint('parent', __name__, subdomain='parent') child = Blueprint('child', __name__, subdomain='child') parent.register_blueprint(child) app.register_blueprint(parent) url_for('parent.child.create', _external=True) \"child.parent.domain.tld\" Blueprint-specific before request functions, etc. registered with the parent will trigger for the child. If a child does not have an error handler that can handle a given exception, the parent’s will be tried. Blueprint Resources¶ Blueprints can provide resources as well. Sometimes you might want to introduce a blueprint only for the resources it provides. Blueprint Resource Folder¶ Like for regular applications, blueprints are considered to be contained in a folder. While multiple blueprints can originate from the same folder, it does not have to be the case and it’s usually not recommended. The folder is inferred from the second argument to Blueprint which is usually __name__. This argument specifies what logical Python module or package corresponds to the blueprint. If it points to an actual Python package that package (which is a folder on the filesystem) is the resource folder. If it’s a module, the package the module is contained in will be the resource folder. You can access the Blueprint.root_path property to see what the resource folder is: >>> simple_page.root_path '/Users/username/TestProject/yourapplication' To quickly open sources from this folder you can use the open_resource() simple_page.open_resource('static/style.css') as = f.read() Static Files¶ A blueprint can expose a folder with static files by providing the path to the folder on the filesystem with the static_folder argument. It is either an absolute path or relative to the blueprint’s = Blueprint('admin', __name__, static_folder='static') By default the rightmost part of the path is where it is exposed on the web. This can be changed with the static_url_path argument. Because the folder is called static here it will be available at the url_prefix of the blueprint + /static. If the blueprint has the prefix /admin, the static URL will be /admin/static. The endpoint is named blueprint_name.static. You can generate URLs to it with url_for() like you would with the static folder of the ('admin.static', filename='style.css') However, if the blueprint does not have a url_prefix, it is not possible to access the blueprint’s static folder. This is because the URL would be /static in this case, and the application’s /static route takes precedence. Unlike template folders, blueprint static folders are not searched if the file does not exist in the application static folder. Templates¶ If you want the blueprint to expose templates you can do that by providing the template_folder parameter to the Blueprint = Blueprint('admin', __name__, template_folder='templates') For static files, the path can be absolute or relative to the blueprint resource folder. The template folder is added to the search path of templates but with a lower priority than the actual application’s template folder. That way you can easily override templates that a blueprint provides in the actual application. This also means that if you don’t want a blueprint template to be accidentally overridden, make sure that no other blueprint or actual application template has the same relative path. When multiple blueprints provide the same relative template path the first blueprint registered takes precedence over the others. So if you have a blueprint in the folder yourapplication/admin and you want to render the template 'admin/index.html' and you have provided templates as a template_folder you will have to create a file like /admin/templates/admin/index.html. The reason for the extra admin folder is to avoid getting our template overridden by a template named index.html in the actual application template folder. To further reiterate you have a blueprint named admin and you want to render a template called index.html which is specific to this blueprint, the best idea is to lay out your templates like / blueprints/ admin/ templates/ admin/ index.html __init__.py And then when you want to render the template, use admin/index.html as the name to look up the template by. If you encounter problems loading the correct templates enable the EXPLAIN_TEMPLATE_LOADING config variable which will instruct Flask to print out the steps it goes through to locate templates on every render_template call. Building URLs¶ If you want to link from one page to another you can use the url_for() function just like you normally would do just that you prefix the URL endpoint with the name of the blueprint and a dot (.): url_for('admin.index') Additionally if you are in a view function of a blueprint or a rendered template and you want to link to another endpoint of the same blueprint, you can use relative redirects by prefixing the endpoint with a dot ('.index') This will link to admin.index for instance in case the current request was dispatched to any other admin blueprint endpoint. Blueprint Error Handlers¶ Blueprints support the errorhandler decorator just like the Flask application object, so it is easy to make Blueprint-specific custom error pages. Here is an example for a “404 Page Not Found” exception: @simple_page.errorhandler(404) def page_not_found(e): return render_template('pages/404.html') Most error handlers will simply work as expected; however, there is a caveat concerning handlers for 404 and 405 exceptions. These error handlers are only invoked from an appropriate raise statement or a call to abort in another of the blueprint’s view functions; they are not invoked by, e.g., an invalid URL access. This is because the blueprint does not “own” a certain URL space, so the application instance has no way of knowing which blueprint error handler it should run if given an invalid URL. If you would like to execute different handling strategies for these errors based on URL prefixes, they may be defined at the application level using the request proxy object: @app.errorhandler(404) @app.errorhandler(405) def _handle_api_error(ex): if request.path.startswith('/api/'): return jsonify(error=str(ex)), ex.code ex See Handling Application Errors. Contents Modular Applications with Blueprints Why Blueprints? The Concept of Blueprints My First Blueprint Registering Blueprints Nesting Blueprints Blueprint Resources Blueprint Resource Folder Static Files Templates Building URLs Blueprint Error Handlers Navigation Overview Request Context Quick search\n\nExample:\n```text\nfrom flask import Blueprint, render_template, abort\nfrom jinja2 import TemplateNotFound\n\nsimple_page = Blueprint('simple_page', __name__,\n                        template_folder='templates')\n\n@simple_page.route('/', defaults={'page': 'index'})\n@simple_page.route('/<page>')\ndef show(page):\n    try:\n        return render_template(f'pages/{page}.html')\n    except TemplateNotFound:\n        abort(404)\n```\n\nExample:\n```text\nfrom flask import Flask\nfrom yourapplication.simple_page import simple_page\n\napp = Flask(__name__)\napp.register_blueprint(simple_page)\n```\n\nExample:\n```text\n>>> app.url_map\nMap([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,\n <Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,\n <Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>])\n```\n\nExample:\n```text\napp.register_blueprint(simple_page, url_prefix='/pages')\n```\n\nExample:\n```text\n>>> app.url_map\nMap([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,\n <Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,\n <Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>])\n```\n\nExample:\n```text\nparent = Blueprint('parent', __name__, url_prefix='/parent')\nchild = Blueprint('child', __name__, url_prefix='/child')\nparent.register_blueprint(child)\napp.register_blueprint(parent)\n```\n\nExample:\n```text\nurl_for('parent.child.create')\n/parent/child/create\n```\n\nExample:\n```text\nparent = Blueprint('parent', __name__, subdomain='parent')\nchild = Blueprint('child', __name__, subdomain='child')\nparent.register_blueprint(child)\napp.register_blueprint(parent)\n\nurl_for('parent.child.create', _external=True)\n\"child.parent.domain.tld\"\n```\n\nExample:\n```text\n>>> simple_page.root_path\n'/Users/username/TestProject/yourapplication'\n```\n\nExample:\n```text\nwith simple_page.open_resource('static/style.css') as f:\n    code = f.read()\n```\n\nExample:\n```text\nadmin = Blueprint('admin', __name__, static_folder='static')\n```\n\nExample:\n```text\nurl_for('admin.static', filename='style.css')\n```\n\nExample:\n```text\nadmin = Blueprint('admin', __name__, template_folder='templates')\n```\n\nExample:\n```text\nyourpackage/\n    blueprints/\n        admin/\n            templates/\n                admin/\n                    index.html\n            __init__.py\n```\n\nExample:\n```text\nurl_for('admin.index')\n```\n\nExample:\n```text\nurl_for('.index')\n```\n\nExample:\n```text\n@simple_page.errorhandler(404)\ndef page_not_found(e):\n    return render_template('pages/404.html')\n```\n\nExample:\n```text\n@app.errorhandler(404)\n@app.errorhandler(405)\ndef _handle_api_error(ex):\n    if request.path.startswith('/api/'):\n        return jsonify(error=str(ex)), ex.code\n    else:\n        return ex\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.066Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":18,"totalLines":141,"estimatedTokens":3546}}41{"id":"doc-testing_flask_applications_flask_documentation_3-5bd8de48","source":"documentation","title":"Testing Flask Applications — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/testing/","text":"Testing Flask Applications¶ Flask provides utilities for testing an application. This documentation goes over techniques for working with different parts of the application in tests. We will use the pytest framework to set up and run our tests. $ pip install pytest The tutorial goes over how to write tests for 100% coverage of the sample Flaskr blog application. See the tutorial on tests for a detailed explanation of specific tests for an application. Identifying Tests¶ Tests are typically located in the tests folder. Tests are functions that start with test_, in Python modules that start with test_. Tests can also be further grouped in classes that start with Test. It can be difficult to know what to test. Generally, try to test the code that you write, not the code of libraries that you use, since they are already tested. Try to extract complex behaviors as separate functions to test individually. Fixtures¶ Pytest fixtures allow writing pieces of code that are reusable across tests. A simple fixture returns a value, but a fixture can also do setup, yield a value, then do teardown. Fixtures for the application, test client, and CLI runner are shown below, they can be placed in tests/conftest.py. If you’re using an application factory, define an app fixture to create and configure an app instance. You can add code before and after the yield to set up and tear down other resources, such as creating and clearing a database. If you’re not using a factory, you already have an app object you can import and configure directly. You can still use an app fixture to set up and tear down resources. import pytest from my_project import create_app @pytest.fixture() def app(): app = create_app() app.config.update({ \"TESTING\": True, }) # other setup can go here yield app # clean up / reset resources here @pytest.fixture() def client(app): return app.test_client() @pytest.fixture() def runner(app): return app.test_cli_runner() Sending Requests with the Test Client¶ The test client makes requests to the application without running a live server. Flask’s client extends Werkzeug’s client, see those docs for additional information. The client has methods that match the common HTTP request methods, such as client.get() and client.post(). They take many arguments for building the request; you can find the full documentation in EnvironBuilder. Typically you’ll use path, query_string, headers, and data or json. To make a request, call the method the request should use with the path to the route to test. A TestResponse is returned to examine the response data. It has all the usual properties of a response object. You’ll usually look at response.data, which is the bytes returned by the view. If you want to use text, Werkzeug 2.1 provides response.text, or use response.get_data(as_text=True). def test_request_example(client): response = client.get(\"/posts\") assert b\"<h2>Hello, World!</h2>\" in response.data Pass a dict query_string={\"key\": \"value\", ...} to set arguments in the query string (after the ? in the URL). Pass a dict headers={} to set request headers. To send a request body in a POST or PUT request, pass a value to data. If raw bytes are passed, that exact body is used. Usually, you’ll pass a dict to set form data. Form Data¶ To send form data, pass a dict to data. The Content-Type header will be set to multipart/form-data or application/x-www-form-urlencoded automatically. If a value is a file object opened for reading bytes (\"rb\" mode), it will be treated as an uploaded file. To change the detected filename and content type, pass a (file, filename, content_type) tuple. File objects will be closed after making the request, so they do not need to use the usual with open() as It can be useful to store files in a tests/resources folder, then use pathlib.Path to get files relative to the current test file. from pathlib import Path # get the resources folder in the tests folder resources = Path(__file__).parent / \"resources\" def test_edit_user(client): response = client.post(\"/user/2/edit\", data={ \"name\": \"Flask\", \"theme\": \"dark\", \"picture\": (resources / \"picture.png\").open(\"rb\"), }) assert response.status_code == 200 JSON Data¶ To send JSON data, pass an object to json. The Content-Type header will be set to application/json automatically. Similarly, if the response contains JSON data, the response.json attribute will contain the deserialized object. def test_json_data(client): response = client.post(\"/graphql\", json={ \"query\": \"\"\" query User($id: String!) { user(id: $id) { name theme picture_url } } \"\"\", variables={\"id\": 2}, }) assert response.json[\"data\"][\"user\"][\"name\"] == \"Flask\" Following Redirects¶ By default, the client does not make additional requests if the response is a redirect. By passing follow_redirects=True to a request method, the client will continue to make requests until a non-redirect response is returned. TestResponse.history is a tuple of the responses that led up to the final response. Each response has a request attribute which records the request that produced that response. def test_logout_redirect(client): response = client.get(\"/logout\", follow_redirects=True) # Check that there was one redirect response. assert len(response.history) == 1 # Check that the second request was to the index page. assert response.request.path == \"/index\" Accessing and Modifying the Session¶ To access Flask’s context variables, mainly session, use the client in a with statement. The app and request context will remain active after making a request, until the with block ends. from flask import session def test_access_session(client): with (\"/auth/login\", data={\"username\": \"flask\"}) # session is still accessible assert session[\"user_id\"] == 1 # session is no longer accessible If you want to access or set a value in the session before making a request, use the client’s session_transaction() method in a with statement. It returns a session object, and will save the session once the block ends. from flask import session def test_modify_session(client): with client.session_transaction() as session: # set a user id without going through the login route session[\"user_id\"] = 1 # session is saved now response = client.get(\"/users/me\") assert response.json[\"username\"] == \"flask\" Running Commands with the CLI Runner¶ Flask provides test_cli_runner() to create a FlaskCliRunner, which runs CLI commands in isolation and captures the output in a Result object. Flask’s runner extends Click’s runner, see those docs for additional information. Use the runner’s invoke() method to call commands in the same way they would be called with the flask command from the command line. import click @app.cli.command(\"hello\") @click.option(\"--name\", default=\"World\") def hello_command(name): click.echo(f\"Hello, {name}!\") def test_hello_command(runner): result = runner.invoke(args=\"hello\") assert \"World\" in result.output result = runner.invoke(args=[\"hello\", \"--name\", \"Flask\"]) assert \"Flask\" in result.output Tests that depend on an Active Context¶ You may have functions that are called from views or commands, that expect an active application context or request context because they access request, session, or current_app. Rather than testing them by making a request or invoking the command, you can create and activate a context directly. Use with app.app_context() to push an application context. For example, database extensions usually require an active app context to make queries. def test_db_post_model(app): with app.app_context(): post = db.session.query(Post).get(1) Use with app.test_request_context() to push a request context. It takes the same arguments as the test client’s request methods. def test_validate_user_edit(app): with app.test_request_context( \"/user/2/edit\", method=\"POST\", data={\"name\": \"\"} ): # call a function that accesses `request` messages = validate_edit_user() assert messages[\"name\"][0] == \"Name cannot be empty.\" Creating a test request context doesn’t run any of the Flask dispatching code, so before_request functions are not called. If you need to call these, usually it’s better to make a full request instead. However, it’s possible to call them manually. def test_auth_token(app): with app.test_request_context(\"/user/2/edit\", headers={\"X-Auth-Token\": \"1\"}): app.preprocess_request() assert g.user.name == \"Flask\" Contents Testing Flask Applications Identifying Tests Fixtures Sending Requests with the Test Client Form Data JSON Data Following Redirects Accessing and Modifying the Session Running Commands with the CLI Runner Tests that depend on an Active Context Navigation Overview Application Errors Quick search\n\nExample:\n```text\n$ pip install pytest\n```\n\nExample:\n```text\nimport pytest\nfrom my_project import create_app\n\n@pytest.fixture()\ndef app():\n    app = create_app()\n    app.config.update({\n        \"TESTING\": True,\n    })\n\n    # other setup can go here\n\n    yield app\n\n    # clean up / reset resources here\n\n\n@pytest.fixture()\ndef client(app):\n    return app.test_client()\n\n\n@pytest.fixture()\ndef runner(app):\n    return app.test_cli_runner()\n```\n\nExample:\n```text\ndef test_request_example(client):\n    response = client.get(\"/posts\")\n    assert b\"<h2>Hello, World!</h2>\" in response.data\n```\n\nExample:\n```text\nfrom pathlib import Path\n\n# get the resources folder in the tests folder\nresources = Path(__file__).parent / \"resources\"\n\ndef test_edit_user(client):\n    response = client.post(\"/user/2/edit\", data={\n        \"name\": \"Flask\",\n        \"theme\": \"dark\",\n        \"picture\": (resources / \"picture.png\").open(\"rb\"),\n    })\n    assert response.status_code == 200\n```\n\nExample:\n```text\ndef test_json_data(client):\n    response = client.post(\"/graphql\", json={\n        \"query\": \"\"\"\n            query User($id: String!) {\n                user(id: $id) {\n                    name\n                    theme\n                    picture_url\n                }\n            }\n        \"\"\",\n        variables={\"id\": 2},\n    })\n    assert response.json[\"data\"][\"user\"][\"name\"] == \"Flask\"\n```\n\nExample:\n```text\ndef test_logout_redirect(client):\n    response = client.get(\"/logout\", follow_redirects=True)\n    # Check that there was one redirect response.\n    assert len(response.history) == 1\n    # Check that the second request was to the index page.\n    assert response.request.path == \"/index\"\n```\n\nExample:\n```text\nfrom flask import session\n\ndef test_access_session(client):\n    with client:\n        client.post(\"/auth/login\", data={\"username\": \"flask\"})\n        # session is still accessible\n        assert session[\"user_id\"] == 1\n\n    # session is no longer accessible\n```\n\nExample:\n```text\nfrom flask import session\n\ndef test_modify_session(client):\n    with client.session_transaction() as session:\n        # set a user id without going through the login route\n        session[\"user_id\"] = 1\n\n    # session is saved now\n\n    response = client.get(\"/users/me\")\n    assert response.json[\"username\"] == \"flask\"\n```\n\nExample:\n```text\nimport click\n\n@app.cli.command(\"hello\")\n@click.option(\"--name\", default=\"World\")\ndef hello_command(name):\n    click.echo(f\"Hello, {name}!\")\n\ndef test_hello_command(runner):\n    result = runner.invoke(args=\"hello\")\n    assert \"World\" in result.output\n\n    result = runner.invoke(args=[\"hello\", \"--name\", \"Flask\"])\n    assert \"Flask\" in result.output\n```\n\nExample:\n```text\ndef test_db_post_model(app):\n    with app.app_context():\n        post = db.session.query(Post).get(1)\n```\n\nExample:\n```text\ndef test_validate_user_edit(app):\n    with app.test_request_context(\n        \"/user/2/edit\", method=\"POST\", data={\"name\": \"\"}\n    ):\n        # call a function that accesses `request`\n        messages = validate_edit_user()\n\n    assert messages[\"name\"][0] == \"Name cannot be empty.\"\n```\n\nExample:\n```text\ndef test_auth_token(app):\n    with app.test_request_context(\"/user/2/edit\", headers={\"X-Auth-Token\": \"1\"}):\n        app.preprocess_request()\n        assert g.user.name == \"Flask\"\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.069Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":160,"estimatedTokens":2993}}42{"id":"doc-working_with_the_shell_flask_documentation_3_1_x-0d6d4a10","source":"documentation","title":"Working with the Shell — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/shell/","text":"Working with the Shell¶ Changelog Added in version 0.3. One of the reasons everybody loves Python is the interactive shell. It basically allows you to execute Python commands in real time and immediately get results back. Flask itself does not come with an interactive shell, because it does not require any specific setup upfront, just import your application and start playing around. There are however some handy helpers to make playing around in the shell a more pleasant experience. The main issue with interactive console sessions is that you’re not triggering a request like a browser does which means that g, request and others are not available. But the code you want to test might depend on them, so what can you do? This is where some helper functions come in handy. Keep in mind however that these functions are not only there for interactive shell usage, but also for unit testing and other situations that require a faked request context. Generally it’s recommended that you read The Request Context first. Command Line Interface¶ Starting with Flask 0.11 the recommended way to work with the shell is the flask shell command which does a lot of this automatically for you. For instance the shell is automatically initialized with a loaded application context. For more information see Command Line Interface. Creating a Request Context¶ The easiest way to create a proper request context from the shell is by using the test_request_context method which creates us a RequestContext: >>> ctx = app.test_request_context() Normally you would use the with statement to make this request object active, but in the shell it’s easier to use the push() and pop() methods by hand: >>> ctx.push() From that point onwards you can work with the request object until you call pop: >>> ctx.pop() Firing Before/After Request¶ By just creating a request context, you still don’t have run the code that is normally run before a request. This might result in your database being unavailable if you are connecting to the database in a before-request callback or the current user not being stored on the g object etc. This however can easily be done yourself. Just call preprocess_request(): >>> ctx = app.test_request_context() >>> ctx.push() >>> app.preprocess_request() Keep in mind that the preprocess_request() function might return a response object, in that case just ignore it. To shutdown a request, you need to trick a bit before the after request functions (triggered by process_response()) operate on a response object: >>> app.process_response(app.response_class()) <Response 0 bytes [200 OK]> >>> ctx.pop() The functions registered as teardown_request() are automatically called when the context is popped. So this is the perfect place to automatically tear down resources that were needed by the request context (such as database connections). Further Improving the Shell Experience¶ If you like the idea of experimenting in a shell, create yourself a module with stuff you want to star import into your interactive session. There you could also define some more helper methods for common things such as initializing the database, dropping tables etc. Just put them into a module (like shelltools) and import from there: >>> from shelltools import * Contents Working with the Shell Command Line Interface Creating a Request Context Firing Before/After Request Further Improving the Shell Experience Navigation Overview Server for Flask Quick search\n\nExample:\n```text\n>>> ctx = app.test_request_context()\n```\n\nExample:\n```text\n>>> ctx.push()\n```\n\nExample:\n```text\n>>> ctx.pop()\n```\n\nExample:\n```text\n>>> ctx = app.test_request_context()\n>>> ctx.push()\n>>> app.preprocess_request()\n```\n\nExample:\n```text\n>>> app.process_response(app.response_class())\n<Response 0 bytes [200 OK]>\n>>> ctx.pop()\n```\n\nExample:\n```text\n>>> from shelltools import *\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.070Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":37,"estimatedTokens":967}}43{"id":"doc-caching_flask_documentation_3_1_x-e628d2b6","source":"documentation","title":"Caching — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/caching/","text":"Caching¶ When your application runs slow, throw some caches in. Well, at least it’s the easiest way to speed up things. What does a cache do? Say you have a function that takes some time to complete but the results would still be good enough if they were 5 minutes old. So then the idea is that you actually put the result of that calculation into a cache for some time. Flask itself does not provide caching for you, but Flask-Caching, an extension for Flask does. Flask-Caching supports various backends, and it is even possible to develop your own caching backend. Navigation Overview Patterns for Flask Files Decorators Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.070Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":163}}44{"id":"doc-mongodb_with_mongoengine_flask_documentation_3_1-a6dd0ede","source":"documentation","title":"MongoDB with MongoEngine — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/mongoengine/","text":"MongoDB with MongoEngine¶ Using a document database like MongoDB is a common alternative to relational SQL databases. This pattern shows how to use MongoEngine, a document mapper library, to integrate with MongoDB. A running MongoDB server and Flask-MongoEngine are required. pip install flask-mongoengine Configuration¶ Basic setup can be done by defining MONGODB_SETTINGS on app.config and creating a MongoEngine instance. from flask import Flask from flask_mongoengine import MongoEngine app = Flask(__name__) app.config['MONGODB_SETTINGS'] = { \"db\": \"myapp\", } db = MongoEngine(app) Mapping Documents¶ To declare a model that represents a Mongo document, create a class that inherits from Document and declare each of the fields. import mongoengine as me class Movie(me.Document): title = me.StringField(required=True) year = me.IntField() rated = me.StringField() director = me.StringField() actors = me.ListField() If the document has nested fields, use EmbeddedDocument to defined the fields of the embedded document and EmbeddedDocumentField to declare it on the parent document. class Imdb(me.EmbeddedDocument): imdb_id = me.StringField() rating = me.DecimalField() votes = me.IntField() class Movie(me.Document): ... imdb = me.EmbeddedDocumentField(Imdb) Creating Data¶ Instantiate your document class with keyword arguments for the fields. You can also assign values to the field attributes after instantiation. Then call doc.save(). bttf = Movie(title=\"Back To The Future\", year=1985) bttf.actors = [ \"Michael J. Fox\", \"Christopher Lloyd\" ] bttf.imdb = Imdb(imdb_id=\"tt0088763\", rating=8.5) bttf.save() Queries¶ Use the class objects attribute to make queries. A keyword argument looks for an equal value on the field. bttf = Movie.objects(title=\"Back To The Future\").get_or_404() Query operators may be used by concatenating them with the field name using a double-underscore. objects, and queries returned by calling it, are iterable. some_theron_movie = Movie.objects(actors__in=[\"Charlize Theron\"]).first() for recents in Movie.objects(year__gte=2017): print(recents.title) Documentation¶ There are many more ways to define and query documents with MongoEngine. For more information, check out the official documentation. Flask-MongoEngine adds helpful utilities on top of MongoEngine. Check out their documentation as well. Contents MongoDB with MongoEngine Configuration Mapping Documents Creating Data Queries Documentation Navigation Overview Patterns for Flask Loading Views a favicon Quick search\n\nExample:\n```text\npip install flask-mongoengine\n```\n\nExample:\n```text\nfrom flask import Flask\nfrom flask_mongoengine import MongoEngine\n\napp = Flask(__name__)\napp.config['MONGODB_SETTINGS'] = {\n    \"db\": \"myapp\",\n}\ndb = MongoEngine(app)\n```\n\nExample:\n```text\nimport mongoengine as me\n\nclass Movie(me.Document):\n    title = me.StringField(required=True)\n    year = me.IntField()\n    rated = me.StringField()\n    director = me.StringField()\n    actors = me.ListField()\n```\n\nExample:\n```text\nclass Imdb(me.EmbeddedDocument):\n    imdb_id = me.StringField()\n    rating = me.DecimalField()\n    votes = me.IntField()\n\nclass Movie(me.Document):\n    ...\n    imdb = me.EmbeddedDocumentField(Imdb)\n```\n\nExample:\n```text\nbttf = Movie(title=\"Back To The Future\", year=1985)\nbttf.actors = [\n    \"Michael J. Fox\",\n    \"Christopher Lloyd\"\n]\nbttf.imdb = Imdb(imdb_id=\"tt0088763\", rating=8.5)\nbttf.save()\n```\n\nExample:\n```text\nbttf = Movie.objects(title=\"Back To The Future\").get_or_404()\n```\n\nExample:\n```text\nsome_theron_movie = Movie.objects(actors__in=[\"Charlize Theron\"]).first()\n\nfor recents in Movie.objects(year__gte=2017):\n    print(recents.title)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.071Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":68,"estimatedTokens":919}}45{"id":"doc-large_applications_as_packages_flask_documentati-95c9ad00","source":"documentation","title":"Large Applications as Packages — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/packages/","text":"Large Applications as Packages¶ Imagine a simple flask application structure that looks like this: /yourapplication yourapplication.py /static style.css /templates layout.html index.html login.html ... While this is fine for small applications, for larger applications it’s a good idea to use a package instead of a module. The Tutorial is structured to use the package pattern, see the example code. Simple Packages¶ To convert that into a larger one, just create a new folder yourapplication inside the existing one and move everything below it. Then rename yourapplication.py to __init__.py. (Make sure to delete all .pyc files first, otherwise things would most likely break) You should then end up with something like that: /yourapplication /yourapplication __init__.py /static style.css /templates layout.html index.html login.html ... But how do you run your application now? The naive python yourapplication/__init__.py will not work. Let’s just say that Python does not want modules in packages to be the startup file. But that is not a big problem, just add a new file called pyproject.toml next to the inner yourapplication folder with the following contents: [project] name = \"yourapplication\" dependencies = [ \"flask\", ] [build-system] requires = [\"flit_core<4\"] build-backend = \"flit_core.buildapi\" Install your application so it is importable: $ pip install -e . To use the flask command and run your application you need to set the --app option that tells Flask where to find the application instance: $ flask --app yourapplication run What did we gain from this? Now we can restructure the application a bit into multiple modules. The only thing you have to remember is the following quick Flask application object creation has to be in the __init__.py file. That way each module can import it safely and the __name__ variable will resolve to the correct package. all the view functions (the ones with a route() decorator on top) have to be imported in the __init__.py file. Not the object itself, but the module it is in. Import the view module after the application object is created. Here’s an example __init__.py: from flask import Flask app = Flask(__name__) import yourapplication.views And this is what views.py would look yourapplication import app @app.route('/') def index(): return 'Hello World!' You should then end up with something like that: /yourapplication pyproject.toml /yourapplication __init__.py views.py /static style.css /templates layout.html index.html login.html ... Circular Imports Every Python programmer hates them, and yet we just added imports (That’s when two modules depend on each other. In this case views.py depends on __init__.py). Be advised that this is a bad idea in general but here it is actually fine. The reason for this is that we are not actually using the views in __init__.py and just ensuring the module is imported and we are doing that at the bottom of the file. Working with Blueprints¶ If you have larger applications it’s recommended to divide them into smaller groups where each group is implemented with the help of a blueprint. For a gentle introduction into this topic refer to the Modular Applications with Blueprints chapter of the documentation. Contents Large Applications as Packages Simple Packages Working with Blueprints Navigation Overview Patterns for Flask for Flask Factories Quick search\n\nExample:\n```text\n/yourapplication\n    yourapplication.py\n    /static\n        style.css\n    /templates\n        layout.html\n        index.html\n        login.html\n        ...\n```\n\nExample:\n```text\n/yourapplication\n    /yourapplication\n        __init__.py\n        /static\n            style.css\n        /templates\n            layout.html\n            index.html\n            login.html\n            ...\n```\n\nExample:\n```text\n[project]\nname = \"yourapplication\"\ndependencies = [\n    \"flask\",\n]\n\n[build-system]\nrequires = [\"flit_core<4\"]\nbuild-backend = \"flit_core.buildapi\"\n```\n\nExample:\n```text\n$ pip install -e .\n```\n\nExample:\n```text\n$ flask --app yourapplication run\n```\n\nExample:\n```text\nfrom flask import Flask\napp = Flask(__name__)\n\nimport yourapplication.views\n```\n\nExample:\n```text\nfrom yourapplication import app\n\n@app.route('/')\ndef index():\n    return 'Hello World!'\n```\n\nExample:\n```text\n/yourapplication\n    pyproject.toml\n    /yourapplication\n        __init__.py\n        views.py\n        /static\n            style.css\n        /templates\n            layout.html\n            index.html\n            login.html\n            ...\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.071Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":8,"totalLines":86,"estimatedTokens":1131}}46{"id":"doc-class_based_views_flask_documentation_3_1_x-c515be90","source":"documentation","title":"Class-based Views — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/views/","text":"Class-based Views¶ This page introduces using the View and MethodView classes to write class-based views. A class-based view is a class that acts as a view function. Because it is a class, different instances of the class can be created with different arguments, to change the behavior of the view. This is also known as generic, reusable, or pluggable views. An example of where this is useful is defining a class that creates an API based on the database model it is initialized with. For more complex API behavior and customization, look into the various API extensions for Flask. Basic Reusable View¶ Let’s walk through an example converting a view function to a view class. We start with a view function that queries a list of users then renders a template to show the list. @app.route(\"/users/\") def user_list(): users = User.query.all() return render_template(\"users.html\", users=users) This works for the user model, but let’s say you also had more models that needed list pages. You’d need to write another view function for each model, even though the only thing that would change is the model and template name. Instead, you can write a View subclass that will query a model and render a template. As the first step, we’ll convert the view to a class without any customization. from flask.views import View class UserList(View): def dispatch_request(self): users = User.query.all() return render_template(\"users.html\", objects=users) app.add_url_rule(\"/users/\", view_func=UserList.as_view(\"user_list\")) The View.dispatch_request() method is the equivalent of the view function. Calling View.as_view() method will create a view function that can be registered on the app with its add_url_rule() method. The first argument to as_view is the name to use to refer to the view with url_for(). Note You can’t decorate the class with @app.route() the way you’d do with a basic view function. Next, we need to be able to register the same view class for different models and templates, to make it more useful than the original function. The class will take two arguments, the model and template, and store them on self. Then dispatch_request can reference these instead of hard-coded values. class ListView(View): def __init__(self, model, template): self.model = model self.template = template def dispatch_request(self): items = self.model.query.all() return render_template(self.template, items=items) Remember, we create the view function with View.as_view() instead of creating the class directly. Any extra arguments passed to as_view are then passed when creating the class. Now we can register the same view to handle multiple models. app.add_url_rule( \"/users/\", view_func=ListView.as_view(\"user_list\", User, \"users.html\"), ) app.add_url_rule( \"/stories/\", view_func=ListView.as_view(\"story_list\", Story, \"stories.html\"), ) URL Variables¶ Any variables captured by the URL are passed as keyword arguments to the dispatch_request method, as they would be for a regular view function. class DetailView(View): def __init__(self, model): self.model = model self.template = f\"{model.__name__.lower()}/detail.html\" def dispatch_request(self, id) item = self.model.query.get_or_404(id) return render_template(self.template, item=item) app.add_url_rule( \"/users/<int:id>\", view_func=DetailView.as_view(\"user_detail\", User) ) View Lifetime and self¶ By default, a new instance of the view class is created every time a request is handled. This means that it is safe to write other data to self during the request, since the next request will not see it, unlike other forms of global state. However, if your view class needs to do a lot of complex initialization, doing it for every request is unnecessary and can be inefficient. To avoid this, set View.init_every_request to False, which will only create one instance of the class and use it for every request. In this case, writing to self is not safe. If you need to store data during the request, use g instead. In the ListView example, nothing writes to self during the request, so it is more efficient to create a single instance. class ListView(View): init_every_request = False def __init__(self, model, template): self.model = model self.template = template def dispatch_request(self): items = self.model.query.all() return render_template(self.template, items=items) Different instances will still be created each for each as_view call, but not for each request to those views. View Decorators¶ The view class itself is not the view function. View decorators need to be applied to the view function returned by as_view, not the class itself. Set View.decorators to a list of decorators to apply. class UserList(View): decorators = [cache(minutes=2), login_required] app.add_url_rule('/users/', view_func=UserList.as_view()) If you didn’t set decorators, you could apply them manually instead. This is equivalent = UserList.as_view(\"users_list\") view = cache(minutes=2)(view) view = login_required(view) app.add_url_rule('/users/', view_func=view) Keep in mind that order matters. If you’re used to @decorator style, this is equivalent to: @app.route(\"/users/\") @login_required @cache(minutes=2) def user_list(): ... Method Hints¶ A common pattern is to register a view with methods=[\"GET\", \"POST\"], then check request.method == \"POST\" to decide what to do. Setting View.methods is equivalent to passing the list of methods to add_url_rule or route. class MyView(View): methods = [\"GET\", \"POST\"] def dispatch_request(self): if request.method == \"POST\": ... ... app.add_url_rule('/my-view', view_func=MyView.as_view('my-view')) This is equivalent to the following, except further subclasses can inherit or change the methods. app.add_url_rule( \"/my-view\", view_func=MyView.as_view(\"my-view\"), methods=[\"GET\", \"POST\"], ) Method Dispatching and APIs¶ For APIs it can be helpful to use a different function for each HTTP method. MethodView extends the basic View to dispatch to different methods of the class based on the request method. Each HTTP method maps to a method of the class with the same (lowercase) name. MethodView automatically sets View.methods based on the methods defined by the class. It even knows how to handle subclasses that override or define other methods. We can make a generic ItemAPI class that provides get (detail), patch (edit), and delete methods for a given model. A GroupAPI can provide get (list) and post (create) methods. from flask.views import MethodView class ItemAPI(MethodView): init_every_request = False def __init__(self, model): self.model = model self.validator = generate_validator(model) def _get_item(self, id): return self.model.query.get_or_404(id) def get(self, id): item = self._get_item(id) return jsonify(item.to_json()) def patch(self, id): item = self._get_item(id) errors = self.validator.validate(item, request.json) if jsonify(errors), 400 item.update_from_json(request.json) db.session.commit() return jsonify(item.to_json()) def delete(self, id): item = self._get_item(id) db.session.delete(item) db.session.commit() return \"\", 204 class GroupAPI(MethodView): init_every_request = False def __init__(self, model): self.model = model self.validator = generate_validator(model, create=True) def get(self): items = self.model.query.all() return jsonify([item.to_json() for item in items]) def post(self): errors = self.validator.validate(request.json) if jsonify(errors), 400 db.session.add(self.model.from_json(request.json)) db.session.commit() return jsonify(item.to_json()) def register_api(app, model, name): item = ItemAPI.as_view(f\"{name}-item\", model) group = GroupAPI.as_view(f\"{name}-group\", model) app.add_url_rule(f\"/{name}/<int:id>\", view_func=item) app.add_url_rule(f\"/{name}/\", view_func=group) register_api(app, User, \"users\") register_api(app, Story, \"stories\") This produces the following views, a standard REST API! URL Method Description /users/ GET List all users /users/ POST Create a new user /users/<id> GET Show a single user /users/<id> PATCH Update a user /users/<id> DELETE Delete a user /stories/ GET List all stories /stories/ POST Create a new story /stories/<id> GET Show a single story /stories/<id> PATCH Update a story /stories/<id> DELETE Delete a story Contents Class-based Views Basic Reusable View URL Variables View Lifetime and self View Decorators Method Hints Method Dispatching and APIs Navigation Overview Structure and Lifecycle Quick search\n\nExample:\n```text\n@app.route(\"/users/\")\ndef user_list():\n    users = User.query.all()\n    return render_template(\"users.html\", users=users)\n```\n\nExample:\n```text\nfrom flask.views import View\n\nclass UserList(View):\n    def dispatch_request(self):\n        users = User.query.all()\n        return render_template(\"users.html\", objects=users)\n\napp.add_url_rule(\"/users/\", view_func=UserList.as_view(\"user_list\"))\n```\n\nExample:\n```text\nclass ListView(View):\n    def __init__(self, model, template):\n        self.model = model\n        self.template = template\n\n    def dispatch_request(self):\n        items = self.model.query.all()\n        return render_template(self.template, items=items)\n```\n\nExample:\n```text\napp.add_url_rule(\n    \"/users/\",\n    view_func=ListView.as_view(\"user_list\", User, \"users.html\"),\n)\napp.add_url_rule(\n    \"/stories/\",\n    view_func=ListView.as_view(\"story_list\", Story, \"stories.html\"),\n)\n```\n\nExample:\n```text\nclass DetailView(View):\n    def __init__(self, model):\n        self.model = model\n        self.template = f\"{model.__name__.lower()}/detail.html\"\n\n    def dispatch_request(self, id)\n        item = self.model.query.get_or_404(id)\n        return render_template(self.template, item=item)\n\napp.add_url_rule(\n    \"/users/<int:id>\",\n    view_func=DetailView.as_view(\"user_detail\", User)\n)\n```\n\nExample:\n```text\nclass ListView(View):\n    init_every_request = False\n\n    def __init__(self, model, template):\n        self.model = model\n        self.template = template\n\n    def dispatch_request(self):\n        items = self.model.query.all()\n        return render_template(self.template, items=items)\n```\n\nExample:\n```text\nclass UserList(View):\n    decorators = [cache(minutes=2), login_required]\n\napp.add_url_rule('/users/', view_func=UserList.as_view())\n```\n\nExample:\n```text\nview = UserList.as_view(\"users_list\")\nview = cache(minutes=2)(view)\nview = login_required(view)\napp.add_url_rule('/users/', view_func=view)\n```\n\nExample:\n```text\n@app.route(\"/users/\")\n@login_required\n@cache(minutes=2)\ndef user_list():\n    ...\n```\n\nExample:\n```text\nclass MyView(View):\n    methods = [\"GET\", \"POST\"]\n\n    def dispatch_request(self):\n        if request.method == \"POST\":\n            ...\n        ...\n\napp.add_url_rule('/my-view', view_func=MyView.as_view('my-view'))\n```\n\nExample:\n```text\napp.add_url_rule(\n    \"/my-view\",\n    view_func=MyView.as_view(\"my-view\"),\n    methods=[\"GET\", \"POST\"],\n)\n```\n\nExample:\n```text\nfrom flask.views import MethodView\n\nclass ItemAPI(MethodView):\n    init_every_request = False\n\n    def __init__(self, model):\n        self.model = model\n        self.validator = generate_validator(model)\n\n    def _get_item(self, id):\n        return self.model.query.get_or_404(id)\n\n    def get(self, id):\n        item = self._get_item(id)\n        return jsonify(item.to_json())\n\n    def patch(self, id):\n        item = self._get_item(id)\n        errors = self.validator.validate(item, request.json)\n\n        if errors:\n            return jsonify(errors), 400\n\n        item.update_from_json(request.json)\n        db.session.commit()\n        return jsonify(item.to_json())\n\n    def delete(self, id):\n        item = self._get_item(id)\n        db.session.delete(item)\n        db.session.commit()\n        return \"\", 204\n\nclass GroupAPI(MethodView):\n    init_every_request = False\n\n    def __init__(self, model):\n        self.model = model\n        self.validator = generate_validator(model, create=True)\n\n    def get(self):\n        items = self.model.query.all()\n        return jsonify([item.to_json() for item in items])\n\n    def post(self):\n        errors = self.validator.validate(request.json)\n\n        if errors:\n            return jsonify(errors), 400\n\n        db.session.add(self.model.from_json(request.json))\n        db.session.commit()\n        return jsonify(item.to_json())\n\ndef register_api(app, model, name):\n    item = ItemAPI.as_view(f\"{name}-item\", model)\n    group = GroupAPI.as_view(f\"{name}-group\", model)\n    app.add_url_rule(f\"/{name}/<int:id>\", view_func=item)\n    app.add_url_rule(f\"/{name}/\", view_func=group)\n\nregister_api(app, User, \"users\")\nregister_api(app, Story, \"stories\")\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.073Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":191,"estimatedTokens":3139}}47{"id":"doc-command_line_interface_flask_documentation_3_1_x-cd8370f4","source":"documentation","title":"Command Line Interface — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/cli/","text":"Command Line Interface¶ Installing Flask installs the flask script, a Click command line interface, in your virtualenv. Executed from the terminal, this script gives access to built-in, extension, and application-defined commands. The --help option will give more information about any commands and options. Application Discovery¶ The flask command is installed by Flask, not your application; it must be told where to find your application in order to use it. The --app option is used to specify how to load the application. While --app supports a variety of options for specifying your application, most use cases should be simple. Here are the typical values: (nothing)The name “app” or “wsgi” is imported (as a “.py” file, or package), automatically detecting an app (app or application) or factory (create_app or make_app). --app helloThe given name is imported, automatically detecting an app (app or application) or factory (create_app or make_app). --app has three optional path that sets the current working directory, a Python file or dotted import path, and an optional variable name of the instance or factory. If the name is a factory, it can optionally be followed by arguments in parentheses. The following values demonstrate these src/helloSets the current working directory to src then imports hello. --app hello.webImports the path hello.web. --app the app2 Flask instance in hello. --app 'hello:create_app(\"dev\")'The create_app factory in hello is called with the string 'dev' as the argument. If --app is not set, the command will try to import “app” or “wsgi” (as a “.py” file, or package) and try to detect an application instance or factory. Within the given import, the command looks for an application instance named app or application, then any application instance. If no instance is found, the command looks for a factory function named create_app or make_app that returns an instance. If parentheses follow the factory name, their contents are parsed as Python literals and passed as arguments and keyword arguments to the function. This means that strings must still be in quotes. Run the Development Server¶ The run command will start the development server. It replaces the Flask.run() method in most cases. $ flask --app hello run * Serving Flask app \"hello\" * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) Warning Do not use this command to run your application in production. Only use the development server during development. The development server is provided for convenience, but is not designed to be particularly secure, stable, or efficient. See Deploying to Production for how to run in production. If another program is already using port 5000, you’ll see OSError: [Errno 98] or OSError: [WinError 10013] when the server tries to start. See Address already in use for how to handle that. Debug Mode¶ In debug mode, the flask run command will enable the interactive debugger and the reloader by default, and make errors easier to see and debug. To enable debug mode, use the --debug option. $ flask --app hello run --debug * Serving Flask app \"hello\" * Debug * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with inotify reloader * Debugger is active! * Debugger The --debug option can also be passed to the top level flask command to enable debug mode for any command. The following two run calls are equivalent. $ flask --app hello --debug run $ flask --app hello run --debug Watch and Ignore Files with the Reloader¶ When using debug mode, the reloader will trigger whenever your Python code or imported modules change. The reloader can watch additional files with the --extra-files option. Multiple paths are separated with :, or ; on Windows. $ flask run --extra-files /file2:dirB/ * Running on http://127.0.0.1:8000/ * Detected change in '/path/to/file1', reloading The reloader can also ignore files using fnmatch patterns with the --exclude-patterns option. Multiple patterns are separated with :, or ; on Windows. Open a Shell¶ To explore the data in your application, you can start an interactive Python shell with the shell command. An application context will be active, and the app instance will be imported. $ flask shell Python 3.10.0 (default, Oct 27 2021, :51) [GCC 11.1.0] on linux [production] Instance: /home/david/Projects/pallets/flask/instance >>> Use shell_context_processor() to add other automatic imports. Environment Variables From dotenv¶ The flask command supports setting any option for any command with environment variables. The variables are named like FLASK_OPTION or FLASK_COMMAND_OPTION, for example FLASK_APP or FLASK_RUN_PORT. Rather than passing options every time you run a command, or environment variables every time you open a new terminal, you can use Flask’s dotenv support to set environment variables automatically. If python-dotenv is installed, running the flask command will set environment variables defined in the files .env and .flaskenv. You can also specify an extra file to load with the --env-file option. Dotenv files can be used to avoid having to set --app or FLASK_APP manually, and to set configuration using environment variables similar to how some deployment services work. Variables set on the command line are used over those set in .env, which are used over those set in .flaskenv. .flaskenv should be used for public variables, such as FLASK_APP, while .env should not be committed to your repository so that it can set private variables. Directories are scanned upwards from the directory you call flask from to locate the files. The files are only loaded by the flask command or calling run(). If you would like to load these files when running in production, you should call load_dotenv() manually. Setting Command Options¶ Click is configured to load default values for command options from environment variables. The variables use the pattern FLASK_COMMAND_OPTION. For example, to set the port for the run command, instead of flask run --port $ export FLASK_RUN_PORT=8000 $ flask run * Running on http://127.0.0.1:8000/ $ set -x FLASK_RUN_PORT 8000 $ flask run * Running on http://127.0.0.1:8000/ > set FLASK_RUN_PORT=8000 > flask run * Running on http://127.0.0.1:8000/ > $env:FLASK_RUN_PORT = 8000 > flask run * Running on http://127.0.0.1:8000/ These can be added to the .flaskenv file just like FLASK_APP to control default command options. Disable dotenv¶ The flask command will show a message if it detects dotenv files but python-dotenv is not installed. $ flask run * are .env files present. Do \"pip install python-dotenv\" to use them. You can tell Flask not to load dotenv files even when python-dotenv is installed by setting the FLASK_SKIP_DOTENV environment variable. This can be useful if you want to load them manually, or if you’re using a project runner that loads them already. Keep in mind that the environment variables must be set before the app loads or it won’t configure as expected. BashFishCMDPowershell$ export FLASK_SKIP_DOTENV=1 $ flask run $ set -x FLASK_SKIP_DOTENV 1 $ flask run > set FLASK_SKIP_DOTENV=1 > flask run > $env:FLASK_SKIP_DOTENV = 1 > flask run Environment Variables From virtualenv¶ If you do not want to install dotenv support, you can still set environment variables by adding them to the end of the virtualenv’s activate script. Activating the virtualenv will set the variables. BashFishCMDPowershellUnix Bash, .venv/bin/activate: $ export FLASK_APP=hello Fish, .venv/bin/activate.fish: $ set -x FLASK_APP hello Windows CMD, .venv\\Scripts\\activate.bat: > set FLASK_APP=hello Windows Powershell, .venv\\Scripts\\activate.ps1: > $env:FLASK_APP = \"hello\" It is preferred to use dotenv support over this, since .flaskenv can be committed to the repository so that it works automatically wherever the project is checked out. Custom Commands¶ The flask command is implemented using Click. See that project’s documentation for full information about writing commands. This example adds the command create-user that takes the argument name. import click from flask import Flask app = Flask(__name__) @app.cli.command(\"create-user\") @click.argument(\"name\") def create_user(name): ... $ flask create-user admin This example adds the same command, but as user create, a command in a group. This is useful if you want to organize multiple related commands. import click from flask import Flask from flask.cli import AppGroup app = Flask(__name__) user_cli = AppGroup('user') @user_cli.command('create') @click.argument('name') def create_user(name): ... app.cli.add_command(user_cli) $ flask user create demo See Running Commands with the CLI Runner for an overview of how to test your custom commands. Registering Commands with Blueprints¶ If your application uses blueprints, you can optionally register CLI commands directly onto them. When your blueprint is registered onto your application, the associated commands will be available to the flask command. By default, those commands will be nested in a group matching the name of the blueprint. from flask import Blueprint bp = Blueprint('students', __name__) @bp.cli.command('create') @click.argument('name') def create(name): ... app.register_blueprint(bp) $ flask students create alice You can alter the group name by specifying the cli_group parameter when creating the Blueprint object, or later with app.register_blueprint(bp, cli_group='...'). The following are = Blueprint('students', __name__, cli_group='other') # or app.register_blueprint(bp, cli_group='other') $ flask other create alice Specifying cli_group=None will remove the nesting and merge the commands directly to the application’s = Blueprint('students', __name__, cli_group=None) # or app.register_blueprint(bp, cli_group=None) $ flask create alice Application Context¶ Commands added using the Flask app’s cli or FlaskGroup command() decorator will be executed with an application context pushed, so your custom commands and parameters have access to the app and its configuration. The with_appcontext() decorator can be used to get the same behavior, but is not needed in most cases. import click from flask.cli import with_appcontext @click.command() @with_appcontext def do_work(): ... app.cli.add_command(do_work) Plugins¶ Flask will automatically load commands specified in the flask.commands entry point. This is useful for extensions that want to add commands when they are installed. Entry points are specified in pyproject.toml: [project.entry-points.\"flask.commands\"] my-command = \"my_extension.commands:cli\" Inside my_extension/commands.py you can then export a Click click @click.command() def cli(): ... Once that package is installed in the same virtualenv as your Flask project, you can run flask my-command to invoke the command. Custom Scripts¶ When you are using the app factory pattern, it may be more convenient to define your own Click script. Instead of using --app and letting Flask load your application, you can create your own Click object and export it as a console script entry point. Create an instance of FlaskGroup and pass it the click from flask import Flask from flask.cli import FlaskGroup def create_app(): app = Flask('wiki') # other setup return app @click.group(cls=FlaskGroup, create_app=create_app) def cli(): \"\"\"Management script for the Wiki application.\"\"\" Define the entry point in pyproject.toml: [project.scripts] wiki = \"wiki:cli\" Install the application in the virtualenv in editable mode and the custom script is available. Note that you don’t need to set --app. $ pip install -e . $ wiki run Errors in Custom Scripts When using a custom script, if you introduce an error in your module-level code, the reloader will fail because it can no longer load the entry point. The flask command, being separate from your code, does not have this issue and is recommended in most cases. PyCharm Integration¶ PyCharm Professional provides a special Flask run configuration to run the development server. For the Community Edition, and for other commands besides run, you need to create a custom run configuration. These instructions should be similar for any other IDE you use. In PyCharm, with your project open, click on Run from the menu bar and go to Edit Configurations. You’ll see a screen similar to you create a configuration for the flask run, you can copy and change it to call any other command. Click the + (Add New Configuration) button and select Python. Give the configuration a name such as “flask run”. Click the Script path dropdown and change it to Module name, then input flask. The Parameters field is set to the CLI command to execute along with any arguments. This example uses --app hello run --debug, which will run the development server in debug mode. --app hello should be the import or file with your Flask app. If you installed your project as a package in your virtualenv, you may uncheck the PYTHONPATH options. This will more accurately match how you deploy later. Click OK to save and close the configuration. Select the configuration in the main PyCharm window and click the play button next to it to run the server. Now that you have a configuration for flask run, you can copy that configuration and change the Parameters argument to run a different CLI command. Contents Command Line Interface Application Discovery Run the Development Server Debug Mode Watch and Ignore Files with the Reloader Open a Shell Environment Variables From dotenv Setting Command Options Disable dotenv Environment Variables From virtualenv Custom Commands Registering Commands with Blueprints Application Context Plugins Custom Scripts PyCharm Integration Navigation Overview Server Quick search\n\nExample:\n```text\n$ flask --app hello run\n * Serving Flask app \"hello\"\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\nExample:\n```text\n$ flask --app hello run --debug\n * Serving Flask app \"hello\"\n * Debug mode: on\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n * Restarting with inotify reloader\n * Debugger is active!\n * Debugger PIN: 223-456-919\n```\n\nExample:\n```text\n$ flask --app hello --debug run\n$ flask --app hello run --debug\n```\n\nExample:\n```text\n$ flask run --extra-files file1:dirA/file2:dirB/\n * Running on http://127.0.0.1:8000/\n * Detected change in '/path/to/file1', reloading\n```\n\nExample:\n```text\n$ flask shell\nPython 3.10.0 (default, Oct 27 2021, 06:59:51) [GCC 11.1.0] on linux\nApp: example [production]\nInstance: /home/david/Projects/pallets/flask/instance\n>>>\n```\n\nExample:\n```text\n$ export FLASK_RUN_PORT=8000\n$ flask run\n * Running on http://127.0.0.1:8000/\n```\n\nExample:\n```text\n$ set -x FLASK_RUN_PORT 8000\n$ flask run\n * Running on http://127.0.0.1:8000/\n```\n\nExample:\n```text\n> set FLASK_RUN_PORT=8000\n> flask run\n * Running on http://127.0.0.1:8000/\n```\n\nExample:\n```text\n> $env:FLASK_RUN_PORT = 8000\n> flask run\n * Running on http://127.0.0.1:8000/\n```\n\nExample:\n```text\n$ flask run\n * Tip: There are .env files present. Do \"pip install python-dotenv\" to use them.\n```\n\nExample:\n```text\n$ export FLASK_SKIP_DOTENV=1\n$ flask run\n```\n\nExample:\n```text\n$ set -x FLASK_SKIP_DOTENV 1\n$ flask run\n```\n\nExample:\n```text\n> set FLASK_SKIP_DOTENV=1\n> flask run\n```\n\nExample:\n```text\n> $env:FLASK_SKIP_DOTENV = 1\n> flask run\n```\n\nExample:\n```text\n$ export FLASK_APP=hello\n```\n\nExample:\n```text\n$ set -x FLASK_APP hello\n```\n\nExample:\n```text\n> set FLASK_APP=hello\n```\n\nExample:\n```text\n> $env:FLASK_APP = \"hello\"\n```\n\nExample:\n```text\nimport click\nfrom flask import Flask\n\napp = Flask(__name__)\n\n@app.cli.command(\"create-user\")\n@click.argument(\"name\")\ndef create_user(name):\n    ...\n```\n\nExample:\n```text\n$ flask create-user admin\n```\n\nExample:\n```text\nimport click\nfrom flask import Flask\nfrom flask.cli import AppGroup\n\napp = Flask(__name__)\nuser_cli = AppGroup('user')\n\n@user_cli.command('create')\n@click.argument('name')\ndef create_user(name):\n    ...\n\napp.cli.add_command(user_cli)\n```\n\nExample:\n```text\n$ flask user create demo\n```\n\nExample:\n```text\nfrom flask import Blueprint\n\nbp = Blueprint('students', __name__)\n\n@bp.cli.command('create')\n@click.argument('name')\ndef create(name):\n    ...\n\napp.register_blueprint(bp)\n```\n\nExample:\n```text\n$ flask students create alice\n```\n\nExample:\n```text\nbp = Blueprint('students', __name__, cli_group='other')\n# or\napp.register_blueprint(bp, cli_group='other')\n```\n\nExample:\n```text\n$ flask other create alice\n```\n\nExample:\n```text\nbp = Blueprint('students', __name__, cli_group=None)\n# or\napp.register_blueprint(bp, cli_group=None)\n```\n\nExample:\n```text\n$ flask create alice\n```\n\nExample:\n```text\nimport click\nfrom flask.cli import with_appcontext\n\n@click.command()\n@with_appcontext\ndef do_work():\n    ...\n\napp.cli.add_command(do_work)\n```\n\nExample:\n```text\n[project.entry-points.\"flask.commands\"]\nmy-command = \"my_extension.commands:cli\"\n```\n\nExample:\n```text\nimport click\n\n@click.command()\ndef cli():\n    ...\n```\n\nExample:\n```text\nimport click\nfrom flask import Flask\nfrom flask.cli import FlaskGroup\n\ndef create_app():\n    app = Flask('wiki')\n    # other setup\n    return app\n\n@click.group(cls=FlaskGroup, create_app=create_app)\ndef cli():\n    \"\"\"Management script for the Wiki application.\"\"\"\n```\n\nExample:\n```text\n[project.scripts]\nwiki = \"wiki:cli\"\n```\n\nExample:\n```text\n$ pip install -e .\n$ wiki run\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.075Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":34,"totalLines":260,"estimatedTokens":4322}}48{"id":"doc-template_inheritance_flask_documentation_3_1_x-17b140e5","source":"documentation","title":"Template Inheritance — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/templateinheritance/","text":"Example:\n```text\n<!doctype html>\n<html>\n  <head>\n    {% block head %}\n    <link rel=\"stylesheet\" href=\"{{ url_for('static', filename='style.css') }}\">\n    <title>{% block title %}{% endblock %} - My Webpage</title>\n    {% endblock %}\n  </head>\n  <body>\n    <div id=\"content\">{% block content %}{% endblock %}</div>\n    <div id=\"footer\">\n      {% block footer %}\n      &copy; Copyright 2010 by <a href=\"http://domain.invalid/\">you</a>.\n      {% endblock %}\n    </div>\n  </body>\n</html>\n```\n\nExample:\n```text\n{% extends \"layout.html\" %}\n{% block title %}Index{% endblock %}\n{% block head %}\n  {{ super() }}\n  <style type=\"text/css\">\n    .important { color: #336699; }\n  </style>\n{% endblock %}\n{% block content %}\n  <h1>Index</h1>\n  <p class=\"important\">\n    Welcome on my awesome homepage.\n{% endblock %}\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.079Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":2,"totalLines":39,"estimatedTokens":206}}49{"id":"doc-application_factories_flask_documentation_3_1_x-bd3743ad","source":"documentation","title":"Application Factories — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/appfactories/","text":"Application Factories¶ If you are already using packages and blueprints for your application (Modular Applications with Blueprints) there are a couple of really nice ways to further improve the experience. A common pattern is creating the application object when the blueprint is imported. But if you move the creation of this object into a function, you can then create multiple instances of this app later. So why would you want to do this? Testing. You can have instances of the application with different settings to test every case. Multiple instances. Imagine you want to run different versions of the same application. Of course you could have multiple instances with different configs set up in your webserver, but if you use factories, you can have multiple instances of the same application running in the same application process which can be handy. So how would you then actually implement that? Basic Factories¶ The idea is to set up the application in a function. Like create_app(config_filename): app = Flask(__name__) app.config.from_pyfile(config_filename) from yourapplication.model import db db.init_app(app) from yourapplication.views.admin import admin from yourapplication.views.frontend import frontend app.register_blueprint(admin) app.register_blueprint(frontend) return app The downside is that you cannot use the application object in the blueprints at import time. You can however use it from within a request. How do you get access to the application with the config? Use flask import current_app, Blueprint, render_template admin = Blueprint('admin', __name__, url_prefix='/admin') @admin.route('/') def index(): return render_template(current_app.config['INDEX_TEMPLATE']) Here we look up the name of a template in the config. Factories & Extensions¶ It’s preferable to create your extensions and app factories so that the extension object does not initially get bound to the application. Using Flask-SQLAlchemy, as an example, you should not do something along those create_app(config_filename): app = Flask(__name__) app.config.from_pyfile(config_filename) db = SQLAlchemy(app) But, rather, in model.py (or equivalent): db = SQLAlchemy() and in your application.py (or equivalent): def create_app(config_filename): app = Flask(__name__) app.config.from_pyfile(config_filename) from yourapplication.model import db db.init_app(app) Using this design pattern, no application-specific state is stored on the extension object, so one extension object can be used for multiple apps. For more information about the design of extensions refer to Flask Extension Development. Using Applications¶ To run such an application, you can use the flask command: $ flask --app hello run Flask will automatically detect the factory if it is named create_app or make_app in hello. You can also pass arguments to the factory like this: $ flask --app 'hello:create_app(local_auth=True)' run Then the create_app factory in hello is called with the keyword argument local_auth=True. See Command Line Interface for more detail. Factory Improvements¶ The factory function above is not very clever, but you can improve it. The following changes are straightforward to it possible to pass in configuration values for unit tests so that you don’t have to create config files on the filesystem. Call a function from a blueprint when the application is setting up so that you have a place to modify attributes of the application (like hooking in before/after request handlers etc.) Add in WSGI middlewares when the application is being created if necessary. Contents Application Factories Basic Factories Factories & Extensions Using Applications Factory Improvements Navigation Overview Patterns for Flask Applications as Packages Dispatching Quick search\n\nExample:\n```text\ndef create_app(config_filename):\n    app = Flask(__name__)\n    app.config.from_pyfile(config_filename)\n\n    from yourapplication.model import db\n    db.init_app(app)\n\n    from yourapplication.views.admin import admin\n    from yourapplication.views.frontend import frontend\n    app.register_blueprint(admin)\n    app.register_blueprint(frontend)\n\n    return app\n```\n\nExample:\n```text\nfrom flask import current_app, Blueprint, render_template\nadmin = Blueprint('admin', __name__, url_prefix='/admin')\n\n@admin.route('/')\ndef index():\n    return render_template(current_app.config['INDEX_TEMPLATE'])\n```\n\nExample:\n```text\ndef create_app(config_filename):\n    app = Flask(__name__)\n    app.config.from_pyfile(config_filename)\n\n    db = SQLAlchemy(app)\n```\n\nExample:\n```text\ndb = SQLAlchemy()\n```\n\nExample:\n```text\ndef create_app(config_filename):\n    app = Flask(__name__)\n    app.config.from_pyfile(config_filename)\n\n    from yourapplication.model import db\n    db.init_app(app)\n```\n\nExample:\n```text\n$ flask --app hello run\n```\n\nExample:\n```text\n$ flask --app 'hello:create_app(local_auth=True)' run\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.079Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":64,"estimatedTokens":1223}}50{"id":"doc-lazily_loading_views_flask_documentation_3_1_x-d236473a","source":"documentation","title":"Lazily Loading Views — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/lazyloading/","text":"Lazily Loading Views¶ Flask is usually used with the decorators. Decorators are simple and you have the URL right next to the function that is called for that specific URL. However there is a downside to this means all your code that uses decorators has to be imported upfront or Flask will never actually find your function. This can be a problem if your application has to import quick. It might have to do that on systems like Google’s App Engine or other systems. So if you suddenly notice that your application outgrows this approach you can fall back to a centralized URL mapping. The system that enables having a central URL map is the add_url_rule() function. Instead of using decorators, you have a file that sets up the application with all URLs. Converting to Centralized URL Map¶ Imagine the current application looks somewhat like flask import Flask app = Flask(__name__) @app.route('/') def index(): pass @app.route('/user/<username>') def user(username): pass Then, with the centralized approach you would have one file with the views (views.py) but without any index(): pass def user(username): pass And then a file that sets up an application which maps the functions to flask import Flask from yourapplication import views app = Flask(__name__) app.add_url_rule('/', view_func=views.index) app.add_url_rule('/user/<username>', view_func=views.user) Loading Late¶ So far we only split up the views and the routing, but the module is still loaded upfront. The trick is to actually load the view function as needed. This can be accomplished with a helper class that behaves just like a function but internally imports the real function on first werkzeug.utils import import_string, cached_property class LazyView(object): def __init__(self, import_name): self.__module__, self.__name__ = import_name.rsplit('.', 1) self.import_name = import_name @cached_property def view(self): return import_string(self.import_name) def __call__(self, *args, **kwargs): return self.view(*args, **kwargs) What’s important here is is that __module__ and __name__ are properly set. This is used by Flask internally to figure out how to name the URL rules in case you don’t provide a name for the rule yourself. Then you can define your central place to combine the views like flask import Flask from yourapplication.helpers import LazyView app = Flask(__name__) app.add_url_rule('/', view_func=LazyView('yourapplication.views.index')) app.add_url_rule('/user/<username>', view_func=LazyView('yourapplication.views.user')) You can further optimize this in terms of amount of keystrokes needed to write this by having a function that calls into add_url_rule() by prefixing a string with the project name and a dot, and by wrapping view_func in a LazyView as needed. def url(import_name, url_rules=[], **options): view = LazyView(f\"yourapplication.{import_name}\") for url_rule in (url_rule, view_func=view, **options) # add a single route to the index view url('views.index', ['/']) # add two routes to a single function endpoint url_rules = ['/user/','/user/<username>'] url('views.user', url_rules) One thing to keep in mind is that before and after request handlers have to be in a file that is imported upfront to work properly on the first request. The same goes for any kind of remaining decorator. Contents Lazily Loading Views Converting to Centralized URL Map Loading Late Navigation Overview Patterns for Flask , fetch, and JSON with MongoEngine Quick search\n\nExample:\n```text\nfrom flask import Flask\napp = Flask(__name__)\n\n@app.route('/')\ndef index():\n    pass\n\n@app.route('/user/<username>')\ndef user(username):\n    pass\n```\n\nExample:\n```text\ndef index():\n    pass\n\ndef user(username):\n    pass\n```\n\nExample:\n```text\nfrom flask import Flask\nfrom yourapplication import views\napp = Flask(__name__)\napp.add_url_rule('/', view_func=views.index)\napp.add_url_rule('/user/<username>', view_func=views.user)\n```\n\nExample:\n```text\nfrom werkzeug.utils import import_string, cached_property\n\nclass LazyView(object):\n\n    def __init__(self, import_name):\n        self.__module__, self.__name__ = import_name.rsplit('.', 1)\n        self.import_name = import_name\n\n    @cached_property\n    def view(self):\n        return import_string(self.import_name)\n\n    def __call__(self, *args, **kwargs):\n        return self.view(*args, **kwargs)\n```\n\nExample:\n```text\nfrom flask import Flask\nfrom yourapplication.helpers import LazyView\napp = Flask(__name__)\napp.add_url_rule('/',\n                 view_func=LazyView('yourapplication.views.index'))\napp.add_url_rule('/user/<username>',\n                 view_func=LazyView('yourapplication.views.user'))\n```\n\nExample:\n```text\ndef url(import_name, url_rules=[], **options):\n    view = LazyView(f\"yourapplication.{import_name}\")\n    for url_rule in url_rules:\n        app.add_url_rule(url_rule, view_func=view, **options)\n\n# add a single route to the index view\nurl('views.index', ['/'])\n\n# add two routes to a single function endpoint\nurl_rules = ['/user/','/user/<username>']\nurl('views.user', url_rules)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.080Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":79,"estimatedTokens":1264}}51{"id":"doc-handling_application_errors_flask_documentation_-bf17509c","source":"documentation","title":"Handling Application Errors — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/errorhandling/","text":"Handling Application Errors¶ Applications fail, servers fail. Sooner or later you will see an exception in production. Even if your code is 100% correct, you will still see exceptions from time to time. Why? Because everything else involved will fail. Here are some situations where perfectly fine code can lead to server client terminated the request early and the application was still reading from the incoming data the database server was overloaded and could not handle the query a filesystem is full a hard drive crashed a backend server overloaded a programming error in a library you are using network connection of the server to another system failed And that’s just a small sample of issues you could be facing. So how do we deal with that sort of problem? By default if your application runs in production mode, and an exception is raised Flask will display a very simple page for you and log the exception to the logger. But there is more you can do, and we will cover some better setups to deal with errors including custom exceptions and 3rd party tools. Error Logging Tools¶ Sending error mails, even if just for critical ones, can become overwhelming if enough users are hitting the error and log files are typically never looked at. This is why we recommend using Sentry for dealing with application errors. It’s available as a source-available project on GitHub and is also available as a hosted version which you can try for free. Sentry aggregates duplicate errors, captures the full stack trace and local variables for debugging, and sends you mails based on new errors or frequency thresholds. To use Sentry you need to install the sentry-sdk client with extra flask dependencies. $ pip install sentry-sdk[flask] And then add this to your Flask sentry_sdk from sentry_sdk.integrations.flask import FlaskIntegration sentry_sdk.init('YOUR_DSN_HERE', integrations=[FlaskIntegration()]) The YOUR_DSN_HERE value needs to be replaced with the DSN value you get from your Sentry installation. After installation, failures leading to an Internal Server Error are automatically reported to Sentry and from there you can receive error notifications. See also supports catching errors from a worker queue (RQ, Celery, etc.) in a similar fashion. See the Python SDK docs for more information. Flask-specific documentation Error Handlers¶ When an error occurs in Flask, an appropriate HTTP status code will be returned. 400-499 indicate errors with the client’s request data, or about the data requested. 500-599 indicate errors with the server or application itself. You might want to show custom error pages to the user when an error occurs. This can be done by registering error handlers. An error handler is a function that returns a response when a type of error is raised, similar to how a view is a function that returns a response when a request URL is matched. It is passed the instance of the error being handled, which is most likely a HTTPException. The status code of the response will not be set to the handler’s code. Make sure to provide the appropriate HTTP status code when returning a response from a handler. Registering¶ Register handlers by decorating a function with errorhandler(). Or use register_error_handler() to register the function later. Remember to set the error code when returning the response. @app.errorhandler(werkzeug.exceptions.BadRequest) def handle_bad_request(e): return 'bad request!', 400 # or, without the decorator app.register_error_handler(400, handle_bad_request) werkzeug.exceptions.HTTPException subclasses like BadRequest and their HTTP codes are interchangeable when registering handlers. (BadRequest.code == 400) Non-standard HTTP codes cannot be registered by code because they are not known by Werkzeug. Instead, define a subclass of HTTPException with the appropriate code and register and raise that exception class. class InsufficientStorage(werkzeug.exceptions.HTTPException): code = 507 description = 'Not enough storage space.' app.register_error_handler(InsufficientStorage, handle_507) raise InsufficientStorage() Handlers can be registered for any exception class, not just HTTPException subclasses or HTTP status codes. Handlers can be registered for a specific class, or for all subclasses of a parent class. Handling¶ When building a Flask application you will run into exceptions. If some part of your code breaks while handling a request (and you have no error handlers registered), a “500 Internal Server Error” (InternalServerError) will be returned by default. Similarly, “404 Not Found” (NotFound) error will occur if a request is sent to an unregistered route. If a route receives an unallowed request method, a “405 Method Not Allowed” (MethodNotAllowed) will be raised. These are all subclasses of HTTPException and are provided by default in Flask. Flask gives you the ability to raise any HTTP exception registered by Werkzeug. However, the default HTTP exceptions return simple exception pages. You might want to show custom error pages to the user when an error occurs. This can be done by registering error handlers. When Flask catches an exception while handling a request, it is first looked up by code. If no handler is registered for the code, Flask looks up the error by its class hierarchy; the most specific handler is chosen. If no handler is registered, HTTPException subclasses show a generic message about their code, while other exceptions are converted to a generic “500 Internal Server Error”. For example, if an instance of ConnectionRefusedError is raised, and a handler is registered for ConnectionError and ConnectionRefusedError, the more specific ConnectionRefusedError handler is called with the exception instance to generate the response. Handlers registered on the blueprint take precedence over those registered globally on the application, assuming a blueprint is handling the request that raises the exception. However, the blueprint cannot handle 404 routing errors because the 404 occurs at the routing level before the blueprint can be determined. Generic Exception Handlers¶ It is possible to register error handlers for very generic base classes such as HTTPException or even Exception. However, be aware that these will catch more than you might expect. For example, an error handler for HTTPException might be useful for turning the default HTML errors pages into JSON. However, this handler will trigger for things you don’t cause directly, such as 404 and 405 errors during routing. Be sure to craft your handler carefully so you don’t lose information about the HTTP error. from flask import json from werkzeug.exceptions import HTTPException @app.errorhandler(HTTPException) def handle_exception(e): \"\"\"Return JSON instead of HTML for HTTP errors.\"\"\" # start with the correct headers and status code from the error response = e.get_response() # replace the body with JSON response.data = json.dumps({ \"code\": e.code, \"name\": e.name, \"description\": e.description, }) response.content_type = \"application/json\" return response An error handler for Exception might seem useful for changing how all errors, even unhandled ones, are presented to the user. However, this is similar to doing except Python, it will capture all otherwise unhandled errors, including all HTTP status codes. In most cases it will be safer to register handlers for more specific exceptions. Since HTTPException instances are valid WSGI responses, you could also pass them through directly. from werkzeug.exceptions import HTTPException @app.errorhandler(Exception) def handle_exception(e): # pass through HTTP errors if isinstance(e, HTTPException): return e # now you're handling non-HTTP exceptions only return render_template(\"500_generic.html\", e=e), 500 Error handlers still respect the exception class hierarchy. If you register handlers for both HTTPException and Exception, the Exception handler will not handle HTTPException subclasses because the HTTPException handler is more specific. Unhandled Exceptions¶ When there is no error handler registered for an exception, a 500 Internal Server Error will be returned instead. See flask.Flask.handle_exception() for information about this behavior. If there is an error handler registered for InternalServerError, this will be invoked. As of Flask 1.1.0, this error handler will always be passed an instance of InternalServerError, not the original unhandled error. The original error is available as e.original_exception. An error handler for “500 Internal Server Error” will be passed uncaught exceptions in addition to explicit 500 errors. In debug mode, a handler for “500 Internal Server Error” will not be used. Instead, the interactive debugger will be shown. Custom Error Pages¶ Sometimes when building a Flask application, you might want to raise a HTTPException to signal to the user that something is wrong with the request. Fortunately, Flask comes with a handy abort() function that aborts a request with a HTTP error from werkzeug as desired. It will also provide a plain black and white error page for you with a basic description, but nothing fancy. Depending on the error code it is less or more likely for the user to actually see such an error. Consider the code below, we might have a user profile route, and if the user fails to pass a username we can raise a “400 Bad Request”. If the user passes a username and we can’t find it, we raise a “404 Not Found”. from flask import abort, render_template, request # a username needs to be supplied in the query args # a successful request would be like /profile?username=jack @app.route(\"/profile\") def user_profile(): username = request.arg.get(\"username\") # if a username isn't supplied in the request, return a 400 bad request if username is (400) user = get_user(username=username) # if a user can't be found by their username, return 404 not found if user is (404) return render_template(\"profile.html\", user=user) Here is another example implementation for a “404 Page Not Found” flask import render_template @app.errorhandler(404) def page_not_found(e): # note that we set the 404 status explicitly return render_template('404.html'), 404 When using Application flask import Flask, render_template def page_not_found(e): return render_template('404.html'), 404 def create_app(config_filename): app = Flask(__name__) app.register_error_handler(404, page_not_found) return app An example template might be this: {% extends \"layout.html\" %} {% block title %}Page Not Found{% endblock %} {% block body %} <h1>Page Not Found</h1> <p>What you were looking for is just not there. <p><a href=\"{{ url_for('index') }}\">go somewhere nice</a> {% endblock %} Further Examples¶ The above examples wouldn’t actually be an improvement on the default exception pages. We can create a custom 500.html template like this: {% extends \"layout.html\" %} {% block title %}Internal Server Error{% endblock %} {% block body %} <h1>Internal Server Error</h1> <p>Oops... we seem to have made a mistake, sorry!</p> <p><a href=\"{{ url_for('index') }}\">Go somewhere nice instead</a> {% endblock %} It can be implemented by rendering the template on “500 Internal Server Error”: from flask import render_template @app.errorhandler(500) def internal_server_error(e): # note that we set the 500 status explicitly return render_template('500.html'), 500 When using Application flask import Flask, render_template def internal_server_error(e): return render_template('500.html'), 500 def create_app(): app = Flask(__name__) app.register_error_handler(500, internal_server_error) return app When using Modular Applications with flask import Blueprint blog = Blueprint('blog', __name__) # as a decorator @blog.errorhandler(500) def internal_server_error(e): return render_template('500.html'), 500 # or with register_error_handler blog.register_error_handler(500, internal_server_error) Blueprint Error Handlers¶ In Modular Applications with Blueprints, most error handlers will work as expected. However, there is a caveat concerning handlers for 404 and 405 exceptions. These error handlers are only invoked from an appropriate raise statement or a call to abort in another of the blueprint’s view functions; they are not invoked by, e.g., an invalid URL access. This is because the blueprint does not “own” a certain URL space, so the application instance has no way of knowing which blueprint error handler it should run if given an invalid URL. If you would like to execute different handling strategies for these errors based on URL prefixes, they may be defined at the application level using the request proxy object. from flask import jsonify, render_template # at the application level # not the blueprint level @app.errorhandler(404) def page_not_found(e): # if a request is in our blog URL space if request.path.startswith('/blog/'): # we return a custom blog 404 page return render_template(\"blog/404.html\"), 404 else: # otherwise we return our generic site-wide 404 page return render_template(\"404.html\"), 404 @app.errorhandler(405) def method_not_allowed(e): # if a request has the wrong method to our API if request.path.startswith('/api/'): # we return a json saying so return jsonify(message=\"Method Not Allowed\"), 405 else: # otherwise we return a generic site-wide 405 page return render_template(\"405.html\"), 405 Returning API Errors as JSON¶ When building APIs in Flask, some developers realise that the built-in exceptions are not expressive enough for APIs and that the content type of text/html they are emitting is not very useful for API consumers. Using the same techniques as above and jsonify() we can return JSON responses to API errors. abort() is called with a description parameter. The error handler will use that as the JSON error message, and set the status code to 404. from flask import abort, jsonify @app.errorhandler(404) def resource_not_found(e): return jsonify(error=str(e)), 404 @app.route(\"/cheese\") def get_one_cheese(): resource = get_resource() if resource is (404, description=\"Resource not found\") return jsonify(resource) We can also create custom exception classes. For instance, we can introduce a new custom exception for an API that can take a proper human readable message, a status code for the error and some optional payload to give more context for the error. This is a simple flask import jsonify, request class InvalidAPIUsage(Exception): status_code = 400 def __init__(self, message, status_code=None, payload=None): super().__init__() self.message = message if status_code is not = status_code self.payload = payload def to_dict(self): rv = dict(self.payload or ()) rv['message'] = self.message return rv @app.errorhandler(InvalidAPIUsage) def invalid_api_usage(e): return jsonify(e.to_dict()), e.status_code # an API app route for getting user information # a correct request might be /api/user?user_id=420 @app.route(\"/api/user\") def user_api(user_id): user_id = request.arg.get(\"user_id\") if not InvalidAPIUsage(\"No user id provided!\") user = get_user(user_id=user_id) if not InvalidAPIUsage(\"No such user!\", status_code=404) return jsonify(user.to_dict()) A view can now raise that exception with an error message. Additionally some extra payload can be provided as a dictionary through the payload parameter. Logging¶ See Logging for information about how to log exceptions, such as by emailing them to admins. Debugging¶ See Debugging Application Errors for information about how to debug errors in development and production. Contents Handling Application Errors Error Logging Tools Error Handlers Registering Handling Generic Exception Handlers Unhandled Exceptions Custom Error Pages Further Examples Blueprint Error Handlers Returning API Errors as JSON Logging Debugging Navigation Overview Flask Applications Application Errors Quick search\n\nExample:\n```text\n$ pip install sentry-sdk[flask]\n```\n\nExample:\n```text\nimport sentry_sdk\nfrom sentry_sdk.integrations.flask import FlaskIntegration\n\nsentry_sdk.init('YOUR_DSN_HERE', integrations=[FlaskIntegration()])\n```\n\nExample:\n```text\n@app.errorhandler(werkzeug.exceptions.BadRequest)\ndef handle_bad_request(e):\n    return 'bad request!', 400\n\n# or, without the decorator\napp.register_error_handler(400, handle_bad_request)\n```\n\nExample:\n```text\nclass InsufficientStorage(werkzeug.exceptions.HTTPException):\n    code = 507\n    description = 'Not enough storage space.'\n\napp.register_error_handler(InsufficientStorage, handle_507)\n\nraise InsufficientStorage()\n```\n\nExample:\n```text\nfrom flask import json\nfrom werkzeug.exceptions import HTTPException\n\n@app.errorhandler(HTTPException)\ndef handle_exception(e):\n    \"\"\"Return JSON instead of HTML for HTTP errors.\"\"\"\n    # start with the correct headers and status code from the error\n    response = e.get_response()\n    # replace the body with JSON\n    response.data = json.dumps({\n        \"code\": e.code,\n        \"name\": e.name,\n        \"description\": e.description,\n    })\n    response.content_type = \"application/json\"\n    return response\n```\n\nExample:\n```text\nfrom werkzeug.exceptions import HTTPException\n\n@app.errorhandler(Exception)\ndef handle_exception(e):\n    # pass through HTTP errors\n    if isinstance(e, HTTPException):\n        return e\n\n    # now you're handling non-HTTP exceptions only\n    return render_template(\"500_generic.html\", e=e), 500\n```\n\nExample:\n```text\nfrom flask import abort, render_template, request\n\n# a username needs to be supplied in the query args\n# a successful request would be like /profile?username=jack\n@app.route(\"/profile\")\ndef user_profile():\n    username = request.arg.get(\"username\")\n    # if a username isn't supplied in the request, return a 400 bad request\n    if username is None:\n        abort(400)\n\n    user = get_user(username=username)\n    # if a user can't be found by their username, return 404 not found\n    if user is None:\n        abort(404)\n\n    return render_template(\"profile.html\", user=user)\n```\n\nExample:\n```text\nfrom flask import render_template\n\n@app.errorhandler(404)\ndef page_not_found(e):\n    # note that we set the 404 status explicitly\n    return render_template('404.html'), 404\n```\n\nExample:\n```text\nfrom flask import Flask, render_template\n\ndef page_not_found(e):\n  return render_template('404.html'), 404\n\ndef create_app(config_filename):\n    app = Flask(__name__)\n    app.register_error_handler(404, page_not_found)\n    return app\n```\n\nExample:\n```text\n{% extends \"layout.html\" %}\n{% block title %}Page Not Found{% endblock %}\n{% block body %}\n  <h1>Page Not Found</h1>\n  <p>What you were looking for is just not there.\n  <p><a href=\"{{ url_for('index') }}\">go somewhere nice</a>\n{% endblock %}\n```\n\nExample:\n```text\n{% extends \"layout.html\" %}\n{% block title %}Internal Server Error{% endblock %}\n{% block body %}\n  <h1>Internal Server Error</h1>\n  <p>Oops... we seem to have made a mistake, sorry!</p>\n  <p><a href=\"{{ url_for('index') }}\">Go somewhere nice instead</a>\n{% endblock %}\n```\n\nExample:\n```text\nfrom flask import render_template\n\n@app.errorhandler(500)\ndef internal_server_error(e):\n    # note that we set the 500 status explicitly\n    return render_template('500.html'), 500\n```\n\nExample:\n```text\nfrom flask import Flask, render_template\n\ndef internal_server_error(e):\n  return render_template('500.html'), 500\n\ndef create_app():\n    app = Flask(__name__)\n    app.register_error_handler(500, internal_server_error)\n    return app\n```\n\nExample:\n```text\nfrom flask import Blueprint\n\nblog = Blueprint('blog', __name__)\n\n# as a decorator\n@blog.errorhandler(500)\ndef internal_server_error(e):\n    return render_template('500.html'), 500\n\n# or with register_error_handler\nblog.register_error_handler(500, internal_server_error)\n```\n\nExample:\n```text\nfrom flask import jsonify, render_template\n\n# at the application level\n# not the blueprint level\n@app.errorhandler(404)\ndef page_not_found(e):\n    # if a request is in our blog URL space\n    if request.path.startswith('/blog/'):\n        # we return a custom blog 404 page\n        return render_template(\"blog/404.html\"), 404\n    else:\n        # otherwise we return our generic site-wide 404 page\n        return render_template(\"404.html\"), 404\n\n@app.errorhandler(405)\ndef method_not_allowed(e):\n    # if a request has the wrong method to our API\n    if request.path.startswith('/api/'):\n        # we return a json saying so\n        return jsonify(message=\"Method Not Allowed\"), 405\n    else:\n        # otherwise we return a generic site-wide 405 page\n        return render_template(\"405.html\"), 405\n```\n\nExample:\n```text\nfrom flask import abort, jsonify\n\n@app.errorhandler(404)\ndef resource_not_found(e):\n    return jsonify(error=str(e)), 404\n\n@app.route(\"/cheese\")\ndef get_one_cheese():\n    resource = get_resource()\n\n    if resource is None:\n        abort(404, description=\"Resource not found\")\n\n    return jsonify(resource)\n```\n\nExample:\n```text\nfrom flask import jsonify, request\n\nclass InvalidAPIUsage(Exception):\n    status_code = 400\n\n    def __init__(self, message, status_code=None, payload=None):\n        super().__init__()\n        self.message = message\n        if status_code is not None:\n            self.status_code = status_code\n        self.payload = payload\n\n    def to_dict(self):\n        rv = dict(self.payload or ())\n        rv['message'] = self.message\n        return rv\n\n@app.errorhandler(InvalidAPIUsage)\ndef invalid_api_usage(e):\n    return jsonify(e.to_dict()), e.status_code\n\n# an API app route for getting user information\n# a correct request might be /api/user?user_id=420\n@app.route(\"/api/user\")\ndef user_api(user_id):\n    user_id = request.arg.get(\"user_id\")\n    if not user_id:\n        raise InvalidAPIUsage(\"No user id provided!\")\n\n    user = get_user(user_id=user_id)\n    if not user:\n        raise InvalidAPIUsage(\"No such user!\", status_code=404)\n\n    return jsonify(user.to_dict())\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.081Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":17,"totalLines":258,"estimatedTokens":5460}}52{"id":"doc-view_decorators_flask_documentation_3_1_x-7419e42b","source":"documentation","title":"View Decorators — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/viewdecorators/","text":"View Decorators¶ Python has a really interesting feature called function decorators. This allows some really neat things for web applications. Because each view in Flask is a function, decorators can be used to inject additional functionality to one or more functions. The route() decorator is the one you probably used already. But there are use cases for implementing your own decorator. For instance, imagine you have a view that should only be used by people that are logged in. If a user goes to the site and is not logged in, they should be redirected to the login page. This is a good example of a use case where a decorator is an excellent solution. Login Required Decorator¶ So let’s implement such a decorator. A decorator is a function that wraps and replaces another function. Since the original function is replaced, you need to remember to copy the original function’s information to the new function. Use functools.wraps() to handle this for you. This example assumes that the login page is called 'login' and that the current user is stored in g.user and is None if there is no-one logged in. from functools import wraps from flask import g, request, redirect, url_for def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if g.user is redirect(url_for('login', next=request.url)) return f(*args, **kwargs) return decorated_function To use the decorator, apply it as innermost decorator to a view function. When applying further decorators, always remember that the route() decorator is the outermost. @app.route('/secret_page') @login_required def secret_page(): pass Note The next value will exist in request.args after a GET request for the login page. You’ll have to pass it along when sending the POST request from the login form. You can do this with a hidden input tag, then retrieve it from request.form when logging the user in. <input type=\"hidden\" value=\"{{ request.args.get('next', '') }}\"/> Caching Decorator¶ Imagine you have a view function that does an expensive calculation and because of that you would like to cache the generated results for a certain amount of time. A decorator would be nice for that. We’re assuming you have set up a cache like mentioned in Caching. Here is an example cache function. It generates the cache key from a specific prefix (actually a format string) and the current path of the request. Notice that we are using a function that first creates the decorator that then decorates the function. Sounds awful? Unfortunately it is a little bit more complex, but the code should still be straightforward to read. The decorated function will then work as follows get the unique cache key for the current request based on the current path. get the value for that key from the cache. If the cache returned something we will return that value. otherwise the original function is called and the return value is stored in the cache for the timeout provided (by default 5 minutes). Here the functools import wraps from flask import request def cached(timeout=5 * 60, key='view/{}'): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): cache_key = key.format(request.path) rv = cache.get(cache_key) if rv is not rv rv = f(*args, **kwargs) cache.set(cache_key, rv, timeout=timeout) return rv return decorated_function return decorator Notice that this assumes an instantiated cache object is available, see Caching. Templating Decorator¶ A common pattern invented by the TurboGears guys a while back is a templating decorator. The idea of that decorator is that you return a dictionary with the values passed to the template from the view function and the template is automatically rendered. With that, the following three examples do exactly the same: @app.route('/') def index(): return render_template('index.html', value=42) @app.route('/') @templated('index.html') def index(): return dict(value=42) @app.route('/') @templated() def index(): return dict(value=42) As you can see, if no template name is provided it will use the endpoint of the URL map with dots converted to slashes + '.html'. Otherwise the provided template name is used. When the decorated function returns, the dictionary returned is passed to the template rendering function. If None is returned, an empty dictionary is assumed, if something else than a dictionary is returned we return it from the function unchanged. That way you can still use the redirect function or return simple strings. Here is the code for that functools import wraps from flask import request, render_template def templated(template=None): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): template_name = template if template_name is = f\"{request.endpoint.replace('.', '/')}.html\" ctx = f(*args, **kwargs) if ctx is = {} elif not isinstance(ctx, dict): return ctx return render_template(template_name, **ctx) return decorated_function return decorator Endpoint Decorator¶ When you want to use the werkzeug routing system for more flexibility you need to map the endpoint as defined in the Rule to a view function. This is possible with this decorator. For flask import Flask from werkzeug.routing import Rule app = Flask(__name__) app.url_map.add(Rule('/', endpoint='index')) @app.endpoint('index') def my_index(): return \"Hello world\" Contents View Decorators Login Required Decorator Caching Decorator Templating Decorator Endpoint Decorator Navigation Overview Patterns for Flask Validation with WTForms Quick search\n\nExample:\n```text\nfrom functools import wraps\nfrom flask import g, request, redirect, url_for\n\ndef login_required(f):\n    @wraps(f)\n    def decorated_function(*args, **kwargs):\n        if g.user is None:\n            return redirect(url_for('login', next=request.url))\n        return f(*args, **kwargs)\n    return decorated_function\n```\n\nExample:\n```text\n@app.route('/secret_page')\n@login_required\ndef secret_page():\n    pass\n```\n\nExample:\n```text\n<input type=\"hidden\" value=\"{{ request.args.get('next', '') }}\"/>\n```\n\nExample:\n```text\nfrom functools import wraps\nfrom flask import request\n\ndef cached(timeout=5 * 60, key='view/{}'):\n    def decorator(f):\n        @wraps(f)\n        def decorated_function(*args, **kwargs):\n            cache_key = key.format(request.path)\n            rv = cache.get(cache_key)\n            if rv is not None:\n                return rv\n            rv = f(*args, **kwargs)\n            cache.set(cache_key, rv, timeout=timeout)\n            return rv\n        return decorated_function\n    return decorator\n```\n\nExample:\n```text\n@app.route('/')\ndef index():\n    return render_template('index.html', value=42)\n\n@app.route('/')\n@templated('index.html')\ndef index():\n    return dict(value=42)\n\n@app.route('/')\n@templated()\ndef index():\n    return dict(value=42)\n```\n\nExample:\n```text\nfrom functools import wraps\nfrom flask import request, render_template\n\ndef templated(template=None):\n    def decorator(f):\n        @wraps(f)\n        def decorated_function(*args, **kwargs):\n            template_name = template\n            if template_name is None:\n                template_name = f\"{request.endpoint.replace('.', '/')}.html\"\n            ctx = f(*args, **kwargs)\n            if ctx is None:\n                ctx = {}\n            elif not isinstance(ctx, dict):\n                return ctx\n            return render_template(template_name, **ctx)\n        return decorated_function\n    return decorator\n```\n\nExample:\n```text\nfrom flask import Flask\nfrom werkzeug.routing import Rule\n\napp = Flask(__name__)\napp.url_map.add(Rule('/', endpoint='index'))\n\n@app.endpoint('index')\ndef my_index():\n    return \"Hello world\"\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.083Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":102,"estimatedTokens":1908}}53{"id":"doc-configuration_handling_flask_documentation_3_1_x-525e96cf","source":"documentation","title":"Configuration Handling — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/config/","text":"Configuration Handling¶ Applications need some kind of configuration. There are different settings you might want to change depending on the application environment like toggling the debug mode, setting the secret key, and other such environment-specific things. The way Flask is designed usually requires the configuration to be available when the application starts up. You can hard code the configuration in the code, which for many small applications is not actually that bad, but there are better ways. Independent of how you load your config, there is a config object available which holds the loaded configuration config attribute of the Flask object. This is the place where Flask itself puts certain configuration values and also where extensions can put their configuration values. But this is also where you can have your own configuration. Configuration Basics¶ The config is actually a subclass of a dictionary and can be modified just like any = Flask(__name__) app.config['TESTING'] = True Certain configuration values are also forwarded to the Flask object so you can read and write them from = True To update multiple keys at once you can use the dict.update() ( TESTING=True, SECRET_KEY='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf' ) Debug Mode¶ The DEBUG config value is special because it may behave inconsistently if changed after the app has begun setting up. In order to set debug mode reliably, use the --debug option on the flask or flask run command. flask run will use the interactive debugger and reloader by default in debug mode. $ flask --app hello run --debug Using the option is recommended. While it is possible to set DEBUG in your config or code, this is strongly discouraged. It can’t be read early by the flask run command, and some systems or extensions may have already configured themselves based on a previous value. Builtin Configuration Values¶ The following configuration values are used internally by ¶ Whether debug mode is enabled. When using flask run to start the development server, an interactive debugger will be shown for unhandled exceptions, and the server will be reloaded when code changes. The debug attribute maps to this config key. This is set with the FLASK_DEBUG environment variable. It may not behave as expected if set in code. Do not enable debug mode when deploying in production. TESTING¶ Enable testing mode. Exceptions are propagated rather than handled by the app’s error handlers. Extensions may also change their behavior to facilitate easier testing. You should enable this in your own tests. PROPAGATE_EXCEPTIONS¶ Exceptions are re-raised rather than being handled by the app’s error handlers. If not set, this is implicitly true if TESTING or DEBUG is enabled. TRAP_HTTP_EXCEPTIONS¶ If there is no handler for an HTTPException-type exception, re-raise it to be handled by the interactive debugger instead of returning it as a simple error response. TRAP_BAD_REQUEST_ERRORS¶ Trying to access a key that doesn’t exist from request dicts like args and form will return a 400 Bad Request error page. Enable this to treat the error as an unhandled exception instead so that you get the interactive debugger. This is a more specific version of TRAP_HTTP_EXCEPTIONS. If unset, it is enabled in debug mode. SECRET_KEY¶ A secret key that will be used for securely signing the session cookie and can be used for any other security related needs by extensions or your application. It should be a long random bytes or str. For example, copy the output of this to your config: $ python -c 'import secrets; print(secrets.token_hex())' '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf' Do not reveal the secret key when posting questions or committing code. SECRET_KEY_FALLBACKS¶ A list of old secret keys that can still be used for unsigning. This allows a project to implement key rotation without invalidating active sessions or other recently-signed secrets. Keys should be removed after an appropriate period of time, as checking each additional key adds some overhead. Order should not matter, but the default implementation will test the last key in the list first, so it might make sense to order oldest to newest. Flask’s built-in secure cookie session supports this. Extensions that use SECRET_KEY may not support this yet. Added in version 3.1. SESSION_COOKIE_NAME¶ The name of the session cookie. Can be changed in case you already have a cookie with the same name. Default: 'session' SESSION_COOKIE_DOMAIN¶ The value of the Domain parameter on the session cookie. If not set, browsers will only send the cookie to the exact domain it was set from. Otherwise, they will send it to any subdomain of the given value as well. Not setting this value is more restricted and secure than setting it. Warning If this is changed after the browser created a cookie is created with one setting, it may result in another being created. Browsers may send send both in an undefined order. In that case, you may want to change SESSION_COOKIE_NAME as well or otherwise invalidate old sessions. Changelog Changed in version 2.3: Not set by default, does not fall back to SERVER_NAME. SESSION_COOKIE_PATH¶ The path that the session cookie will be valid for. If not set, the cookie will be valid underneath APPLICATION_ROOT or / if that is not set. SESSION_COOKIE_HTTPONLY¶ Browsers will not allow JavaScript access to cookies marked as “HTTP only” for security. SESSION_COOKIE_SECURE¶ Browsers will only send cookies with requests over HTTPS if the cookie is marked “secure”. The application must be served over HTTPS for this to make sense. SESSION_COOKIE_PARTITIONED¶ Browsers will send cookies based on the top-level document’s domain, rather than only the domain of the document setting the cookie. This prevents third party cookies set in iframes from “leaking” between separate sites. Browsers are beginning to disallow non-partitioned third party cookies, so you need to mark your cookies partitioned if you expect them to work in such embedded situations. Enabling this implicitly enables SESSION_COOKIE_SECURE as well, as it is only valid when served over HTTPS. Added in version 3.1. SESSION_COOKIE_SAMESITE¶ Restrict how cookies are sent with requests from external sites. Can be set to 'Lax' (recommended) or 'Strict'. See Set-Cookie options. Changelog Added in version 1.0. PERMANENT_SESSION_LIFETIME¶ If session.permanent is true, the cookie’s expiration will be set this number of seconds in the future. Can either be a datetime.timedelta or an int. Flask’s default cookie implementation validates that the cryptographic signature is not older than this value. (days=31) (2678400 seconds) SESSION_REFRESH_EACH_REQUEST¶ Control whether the cookie is sent with every response when session.permanent is true. Sending the cookie every time (the default) can more reliably keep the session from expiring, but uses more bandwidth. Non-permanent sessions are not affected. USE_X_SENDFILE¶ When serving files, set the X-Sendfile header instead of serving the data with Flask. Some web servers, such as Apache, recognize this and serve the data more efficiently. This only makes sense when using such a server. SEND_FILE_MAX_AGE_DEFAULT¶ When serving files, set the cache control max age to this number of seconds. Can be a datetime.timedelta or an int. Override this value on a per-file basis using get_send_file_max_age() on the application or blueprint. If None, send_file tells the browser to use conditional requests will be used instead of a timed cache, which is usually preferable. TRUSTED_HOSTS¶ Validate Request.host and other attributes that use it against these trusted values. Raise a SecurityError if the host is invalid, which results in a 400 error. If it is None, all hosts are valid. Each value is either an exact match, or can start with a dot . to match any subdomain. Validation is done during routing against this value. before_request and after_request callbacks will still be called. Added in version 3.1. SERVER_NAME¶ Inform the application what host and port it is bound to. Must be set if subdomain_matching is enabled, to be able to extract the subdomain from the request. Must be set for url_for to generate external URLs outside of a request context. Changed in version 3.1: Does not restrict requests to only this domain, for both subdomain_matching and host_matching. Changelog Changed in version 2.3: Does not affect SESSION_COOKIE_DOMAIN. Changed in version 1.0: Does not implicitly enable subdomain_matching. APPLICATION_ROOT¶ Inform the application what path it is mounted under by the application / web server. This is used for generating URLs outside the context of a request (inside a request, the dispatcher is responsible for setting SCRIPT_NAME instead; see Application Dispatching for examples of dispatch configuration). Will be used for the session cookie path if SESSION_COOKIE_PATH is not set. Default: '/' PREFERRED_URL_SCHEME¶ Use this scheme for generating external URLs when not in a request context. Default: 'http' MAX_CONTENT_LENGTH¶ The maximum number of bytes that will be read during this request. If this limit is exceeded, a 413 RequestEntityTooLarge error is raised. If it is set to None, no limit is enforced at the Flask application level. However, if it is None and the request has no Content-Length header and the WSGI server does not indicate that it terminates the stream, then no data is read to avoid an infinite stream. Each request defaults to this config. It can be set on a specific Request.max_content_length to apply the limit to that specific view. This should be set appropriately based on an application’s or view’s specific needs. Changelog Added in version 0.6. MAX_FORM_MEMORY_SIZE¶ The maximum size in bytes any non-file form field may be in a multipart/form-data body. If this limit is exceeded, a 413 RequestEntityTooLarge error is raised. If it is set to None, no limit is enforced at the Flask application level. Each request defaults to this config. It can be set on a specific Request.max_form_memory_parts to apply the limit to that specific view. This should be set appropriately based on an application’s or view’s specific needs. Added in version 3.1. MAX_FORM_PARTS¶ The maximum number of fields that may be present in a multipart/form-data body. If this limit is exceeded, a 413 RequestEntityTooLarge error is raised. If it is set to None, no limit is enforced at the Flask application level. Each request defaults to this config. It can be set on a specific Request.max_form_parts to apply the limit to that specific view. This should be set appropriately based on an application’s or view’s specific needs. Added in version 3.1. TEMPLATES_AUTO_RELOAD¶ Reload templates when they are changed. If not set, it will be enabled in debug mode. EXPLAIN_TEMPLATE_LOADING¶ Log debugging information tracing how a template file was loaded. This can be useful to figure out why a template was not loaded or the wrong file appears to be loaded. MAX_COOKIE_SIZE¶ Warn if cookie headers are larger than this many bytes. Defaults to 4093. Larger cookies may be silently ignored by browsers. Set to 0 to disable the warning. PROVIDE_AUTOMATIC_OPTIONS¶ Set to False to disable the automatic addition of OPTIONS responses. This can be overridden per route by altering the provide_automatic_options attribute. Added in version 3.10: Added PROVIDE_AUTOMATIC_OPTIONS to control the default addition of autogenerated OPTIONS responses. Changelog Changed in version 2.3: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, and JSONIFY_PRETTYPRINT_REGULAR were removed. The default app.json provider has equivalent attributes instead. Changed in version 2.3: ENV was removed. Changed in version 2.2: Removed PRESERVE_CONTEXT_ON_EXCEPTION. Changed in version 1.0: LOGGER_NAME and LOGGER_HANDLER_POLICY were removed. See Logging for information about configuration. Added ENV to reflect the FLASK_ENV environment variable. Added SESSION_COOKIE_SAMESITE to control the session cookie’s SameSite option. Added MAX_COOKIE_SIZE to control a warning from Werkzeug. Added in version 0.11: SESSION_REFRESH_EACH_REQUEST, TEMPLATES_AUTO_RELOAD, LOGGER_HANDLER_POLICY, EXPLAIN_TEMPLATE_LOADING Added in version 0.10: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_PRETTYPRINT_REGULAR Added in version 0.9: PREFERRED_URL_SCHEME Added in version 0.8: TRAP_BAD_REQUEST_ERRORS, TRAP_HTTP_EXCEPTIONS, APPLICATION_ROOT, SESSION_COOKIE_DOMAIN, SESSION_COOKIE_PATH, SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE Added in version 0.7: PROPAGATE_EXCEPTIONS, PRESERVE_CONTEXT_ON_EXCEPTION Added in version 0.6: MAX_CONTENT_LENGTH Added in version 0.5: SERVER_NAME Added in version 0.4: LOGGER_NAME Configuring from Python Files¶ Configuration becomes more useful if you can store it in a separate file, ideally located outside the actual application package. You can deploy your application, then separately configure it for the specific deployment. A common pattern is = Flask(__name__) app.config.from_object('yourapplication.default_settings') app.config.from_envvar('YOURAPPLICATION_SETTINGS') This first loads the configuration from the yourapplication.default_settings module and then overrides the values with the contents of the file the YOURAPPLICATION_SETTINGS environment variable points to. This environment variable can be set in the shell before starting the $ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg $ flask run * Running on http://127.0.0.1:5000/ $ set -x YOURAPPLICATION_SETTINGS /path/to/settings.cfg $ flask run * Running on http://127.0.0.1:5000/ > set YOURAPPLICATION_SETTINGS=\\path\\to\\settings.cfg > flask run * Running on http://127.0.0.1:5000/ > $env:YOURAPPLICATION_SETTINGS = \"\\path\\to\\settings.cfg\" > flask run * Running on http://127.0.0.1:5000/ The configuration files themselves are actual Python files. Only values in uppercase are actually stored in the config object later on. So make sure to use uppercase letters for your config keys. Here is an example of a configuration file: # Example configuration SECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf' Make sure to load the configuration very early on, so that extensions have the ability to access the configuration when starting up. There are other methods on the config object as well to load from individual files. For a complete reference, read the Config object’s documentation. Configuring from Data Files¶ It is also possible to load configuration from a file in a format of your choice using from_file(). For example to load from a TOML tomllib app.config.from_file(\"config.toml\", load=tomllib.load, text=False) Or from a JSON json app.config.from_file(\"config.json\", load=json.load) Configuring from Environment Variables¶ In addition to pointing to configuration files using environment variables, you may find it useful (or necessary) to control your configuration values directly from the environment. Flask can be instructed to load all environment variables starting with a specific prefix into the config using from_prefixed_env(). Environment variables can be set in the shell before starting the $ export FLASK_SECRET_KEY=\"5f352379324c22463451387a0aec5d2f\" $ export FLASK_MAIL_ENABLED=false $ flask run * Running on http://127.0.0.1:5000/ $ set -x FLASK_SECRET_KEY \"5f352379324c22463451387a0aec5d2f\" $ set -x FLASK_MAIL_ENABLED false $ flask run * Running on http://127.0.0.1:5000/ > set FLASK_SECRET_KEY=\"5f352379324c22463451387a0aec5d2f\" > set FLASK_MAIL_ENABLED=false > flask run * Running on http://127.0.0.1:5000/ > $env:FLASK_SECRET_KEY = \"5f352379324c22463451387a0aec5d2f\" > $env:FLASK_MAIL_ENABLED = \"false\" > flask run * Running on http://127.0.0.1:5000/ The variables can then be loaded and accessed via the config with a key equal to the environment variable name without the prefix i.e. app.config.from_prefixed_env() app.config[\"SECRET_KEY\"] # Is \"5f352379324c22463451387a0aec5d2f\" The prefix is FLASK_ by default. This is configurable via the prefix argument of from_prefixed_env(). Values will be parsed to attempt to convert them to a more specific type than strings. By default json.loads() is used, so any valid JSON value is possible, including lists and dicts. This is configurable via the loads argument of from_prefixed_env(). When adding a boolean value with the default JSON parsing, only “true” and “false”, lowercase, are valid values. Keep in mind that any non-empty string is considered True by Python. It is possible to set keys in nested dictionaries by separating the keys with double underscore (__). Any intermediate keys that don’t exist on the parent dict will be initialized to an empty dict. $ export FLASK_MYAPI__credentials__username=user123 app.config[\"MYAPI\"][\"credentials\"][\"username\"] # Is \"user123\" On Windows, environment variable keys are always uppercase, therefore the above example would end up as MYAPI__CREDENTIALS__USERNAME. For even more config loading features, including merging and case-insensitive Windows support, try a dedicated library such as Dynaconf, which includes integration with Flask. Configuration Best Practices¶ The downside with the approach mentioned earlier is that it makes testing a little harder. There is no single 100% solution for this problem in general, but there are a couple of things you can keep in mind to improve that your application in a function and register blueprints on it. That way you can create multiple instances of your application with different configurations attached which makes unit testing a lot easier. You can use this to pass in configuration as needed. Do not write code that needs the configuration at import time. If you limit yourself to request-only accesses to the configuration you can reconfigure the object later on as needed. Make sure to load the configuration very early on, so that extensions can access the configuration when calling init_app. Development / Production¶ Most applications need more than one configuration. There should be at least separate configurations for the production server and the one used during development. The easiest way to handle this is to use a default configuration that is always loaded and part of the version control, and a separate configuration that overrides the values as necessary as mentioned in the example = Flask(__name__) app.config.from_object('yourapplication.default_settings') app.config.from_envvar('YOURAPPLICATION_SETTINGS') Then you just have to add a separate config.py file and export YOURAPPLICATION_SETTINGS=/path/to/config.py and you are done. However there are alternative ways as well. For example you could use imports or subclassing. What is very popular in the Django world is to make the import explicit in the config file by adding from yourapplication.default_settings import * to the top of the file and then overriding the changes by hand. You could also inspect an environment variable like YOURAPPLICATION_MODE and set that to production, development etc and import different hard-coded files based on that. An interesting pattern is also to use classes and inheritance for Config(object): TESTING = False class ProductionConfig(Config): DATABASE_URI = 'mysql://user@localhost/foo' class DevelopmentConfig(Config): DATABASE_URI = \"sqlite:////tmp/foo.db\" class TestingConfig(Config): DATABASE_URI = 'sqlite:///:memory:' TESTING = True To enable such a config you just have to call into from_object(): app.config.from_object('configmodule.ProductionConfig') Note that from_object() does not instantiate the class object. If you need to instantiate the class, such as to access a property, then you must do so before calling from_object(): from configmodule import ProductionConfig app.config.from_object(ProductionConfig()) # Alternatively, import via werkzeug.utils import import_string cfg = import_string('configmodule.ProductionConfig')() app.config.from_object(cfg) Instantiating the configuration object allows you to use /foo\" class ProductionConfig(Config): \"\"\"Uses production database server.\"\"\" DB_SERVER = '192.168.19.32' class DevelopmentConfig(Config): DB_SERVER = 'localhost' class TestingConfig(Config): DB_SERVER = 'localhost' DATABASE_URI = 'sqlite:///:memory:' There are many different ways and it’s up to you how you want to manage your configuration files. However here a list of good a default configuration in version control. Either populate the config with this default configuration or import it in your own configuration files before overriding values. Use an environment variable to switch between the configurations. This can be done from outside the Python interpreter and makes development and deployment much easier because you can quickly and easily switch between different configs without having to touch the code at all. If you are working often on different projects you can even create your own script for sourcing that activates a virtualenv and exports the development configuration for you. Use a tool like fabric to push code and configuration separately to the production server(s). Instance Folders¶ Changelog Added in version 0.8. Flask 0.8 introduces instance folders. Flask for a long time made it possible to refer to paths relative to the application’s folder directly (via Flask.root_path). This was also how many developers loaded configurations stored next to the application. Unfortunately however this only works well if applications are not packages in which case the root path refers to the contents of the package. With Flask 0.8 a new attribute was It refers to a new concept called the “instance folder”. The instance folder is designed to not be under version control and be deployment specific. It’s the perfect place to drop things that either change at runtime or configuration files. You can either explicitly provide the path of the instance folder when creating the Flask application or you can let Flask autodetect the instance folder. For explicit configuration use the instance_path = Flask(__name__, instance_path='/path/to/instance/folder') Please keep in mind that this path must be absolute when provided. If the instance_path parameter is not provided the following default locations are module: /myapp.py /instance Uninstalled package: /myapp /__init__.py /instance Installed module or package: $PREFIX/lib/pythonX.Y/site-packages/myapp $PREFIX/var/myapp-instance $PREFIX is the prefix of your Python installation. This can be /usr or the path to your virtualenv. You can print the value of sys.prefix to see what the prefix is set to. Since the config object provided loading of configuration files from relative filenames we made it possible to change the loading via filenames to be relative to the instance path if wanted. The behavior of relative paths in config files can be flipped between “relative to the application root” (the default) to “relative to instance folder” via the instance_relative_config switch to the application = Flask(__name__, instance_relative_config=True) Here is a full example of how to configure Flask to preload the config from a module and then override the config from a file in the instance folder if it = Flask(__name__, instance_relative_config=True) app.config.from_object('yourapplication.default_settings') app.config.from_pyfile('application.cfg', silent=True) The path to the instance folder can be found via the Flask.instance_path. Flask also provides a shortcut to open a file from the instance folder with Flask.open_instance_resource(). Example usage for = os.path.join(app.instance_path, 'application.cfg') with open(filename) as = f.read() # or via app.open_instance_resource('application.cfg') as = f.read() Contents Configuration Handling Configuration Basics Debug Mode Builtin Configuration Values DEBUG TESTING PROPAGATE_EXCEPTIONS TRAP_HTTP_EXCEPTIONS TRAP_BAD_REQUEST_ERRORS SECRET_KEY SECRET_KEY_FALLBACKS SESSION_COOKIE_NAME SESSION_COOKIE_DOMAIN SESSION_COOKIE_PATH SESSION_COOKIE_HTTPONLY SESSION_COOKIE_SECURE SESSION_COOKIE_PARTITIONED SESSION_COOKIE_SAMESITE PERMANENT_SESSION_LIFETIME SESSION_REFRESH_EACH_REQUEST USE_X_SENDFILE SEND_FILE_MAX_AGE_DEFAULT TRUSTED_HOSTS SERVER_NAME APPLICATION_ROOT PREFERRED_URL_SCHEME MAX_CONTENT_LENGTH MAX_FORM_MEMORY_SIZE MAX_FORM_PARTS TEMPLATES_AUTO_RELOAD EXPLAIN_TEMPLATE_LOADING MAX_COOKIE_SIZE PROVIDE_AUTOMATIC_OPTIONS Configuring from Python Files Configuring from Data Files Configuring from Environment Variables Configuration Best Practices Development / Production Instance Folders Navigation Overview Quick search\n\nExample:\n```text\napp = Flask(__name__)\napp.config['TESTING'] = True\n```\n\nExample:\n```text\napp.testing = True\n```\n\nExample:\n```text\napp.config.update(\n    TESTING=True,\n    SECRET_KEY='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'\n)\n```\n\nExample:\n```text\n$ flask --app hello run --debug\n```\n\nExample:\n```text\n$ python -c 'import secrets; print(secrets.token_hex())'\n'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'\n```\n\nExample:\n```text\napp = Flask(__name__)\napp.config.from_object('yourapplication.default_settings')\napp.config.from_envvar('YOURAPPLICATION_SETTINGS')\n```\n\nExample:\n```text\n$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg\n$ flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n$ set -x YOURAPPLICATION_SETTINGS /path/to/settings.cfg\n$ flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n> set YOURAPPLICATION_SETTINGS=\\path\\to\\settings.cfg\n> flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n> $env:YOURAPPLICATION_SETTINGS = \"\\path\\to\\settings.cfg\"\n> flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n# Example configuration\nSECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'\n```\n\nExample:\n```text\nimport tomllib\napp.config.from_file(\"config.toml\", load=tomllib.load, text=False)\n```\n\nExample:\n```text\nimport json\napp.config.from_file(\"config.json\", load=json.load)\n```\n\nExample:\n```text\n$ export FLASK_SECRET_KEY=\"5f352379324c22463451387a0aec5d2f\"\n$ export FLASK_MAIL_ENABLED=false\n$ flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n$ set -x FLASK_SECRET_KEY \"5f352379324c22463451387a0aec5d2f\"\n$ set -x FLASK_MAIL_ENABLED false\n$ flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n> set FLASK_SECRET_KEY=\"5f352379324c22463451387a0aec5d2f\"\n> set FLASK_MAIL_ENABLED=false\n> flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\n> $env:FLASK_SECRET_KEY = \"5f352379324c22463451387a0aec5d2f\"\n> $env:FLASK_MAIL_ENABLED = \"false\"\n> flask run\n * Running on http://127.0.0.1:5000/\n```\n\nExample:\n```text\napp.config.from_prefixed_env()\napp.config[\"SECRET_KEY\"]  # Is \"5f352379324c22463451387a0aec5d2f\"\n```\n\nExample:\n```text\n$ export FLASK_MYAPI__credentials__username=user123\n```\n\nExample:\n```text\napp.config[\"MYAPI\"][\"credentials\"][\"username\"]  # Is \"user123\"\n```\n\nExample:\n```text\nclass Config(object):\n    TESTING = False\n\nclass ProductionConfig(Config):\n    DATABASE_URI = 'mysql://user@localhost/foo'\n\nclass DevelopmentConfig(Config):\n    DATABASE_URI = \"sqlite:////tmp/foo.db\"\n\nclass TestingConfig(Config):\n    DATABASE_URI = 'sqlite:///:memory:'\n    TESTING = True\n```\n\nExample:\n```text\napp.config.from_object('configmodule.ProductionConfig')\n```\n\nExample:\n```text\nfrom configmodule import ProductionConfig\napp.config.from_object(ProductionConfig())\n\n# Alternatively, import via string:\nfrom werkzeug.utils import import_string\ncfg = import_string('configmodule.ProductionConfig')()\napp.config.from_object(cfg)\n```\n\nExample:\n```text\nclass Config(object):\n    \"\"\"Base config, uses staging database server.\"\"\"\n    TESTING = False\n    DB_SERVER = '192.168.1.56'\n\n    @property\n    def DATABASE_URI(self):  # Note: all caps\n        return f\"mysql://user@{self.DB_SERVER}/foo\"\n\nclass ProductionConfig(Config):\n    \"\"\"Uses production database server.\"\"\"\n    DB_SERVER = '192.168.19.32'\n\nclass DevelopmentConfig(Config):\n    DB_SERVER = 'localhost'\n\nclass TestingConfig(Config):\n    DB_SERVER = 'localhost'\n    DATABASE_URI = 'sqlite:///:memory:'\n```\n\nExample:\n```text\napp = Flask(__name__, instance_path='/path/to/instance/folder')\n```\n\nExample:\n```text\n/myapp.py\n/instance\n```\n\nExample:\n```text\n/myapp\n    /__init__.py\n/instance\n```\n\nExample:\n```text\n$PREFIX/lib/pythonX.Y/site-packages/myapp\n$PREFIX/var/myapp-instance\n```\n\nExample:\n```text\napp = Flask(__name__, instance_relative_config=True)\n```\n\nExample:\n```text\napp = Flask(__name__, instance_relative_config=True)\napp.config.from_object('yourapplication.default_settings')\napp.config.from_pyfile('application.cfg', silent=True)\n```\n\nExample:\n```text\nfilename = os.path.join(app.instance_path, 'application.cfg')\nwith open(filename) as f:\n    config = f.read()\n\n# or via open_instance_resource:\nwith app.open_instance_resource('application.cfg') as f:\n    config = f.read()\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.086Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":31,"totalLines":236,"estimatedTokens":7235}}54{"id":"doc-using_url_processors_flask_documentation_3_1_x-43981ba4","source":"documentation","title":"Using URL Processors — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/urlprocessors/","text":"Using URL Processors¶ Changelog Added in version 0.7. Flask 0.7 introduces the concept of URL processors. The idea is that you might have a bunch of resources with common parts in the URL that you don’t always explicitly want to provide. For instance you might have a bunch of URLs that have the language code in it but you don’t want to have to handle it in every single function yourself. URL processors are especially helpful when combined with blueprints. We will handle both application specific URL processors here as well as blueprint specifics. Internationalized Application URLs¶ Consider an application like flask import Flask, g app = Flask(__name__) @app.route('/<lang_code>/') def index(lang_code): g.lang_code = lang_code ... @app.route('/<lang_code>/about') def about(lang_code): g.lang_code = lang_code ... This is an awful lot of repetition as you have to handle the language code setting on the g object yourself in every single function. Sure, a decorator could be used to simplify this, but if you want to generate URLs from one function to another you would have to still provide the language code explicitly which can be annoying. For the latter, this is where url_defaults() functions come in. They can automatically inject values into a call to url_for(). The code below checks if the language code is not yet in the dictionary of URL values and if the endpoint wants a value named 'lang_code': @app.url_defaults def add_language_code(endpoint, values): if 'lang_code' in values or not g.lang_code: return if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'): values['lang_code'] = g.lang_code The method is_endpoint_expecting() of the URL map can be used to figure out if it would make sense to provide a language code for the given endpoint. The reverse of that function are url_value_preprocessor()s. They are executed right after the request was matched and can execute code based on the URL values. The idea is that they pull information out of the values dictionary and put it somewhere else: @app.url_value_preprocessor def pull_lang_code(endpoint, values): g.lang_code = values.pop('lang_code', None) That way you no longer have to do the lang_code assignment to g in every function. You can further improve that by writing your own decorator that prefixes URLs with the language code, but the more beautiful solution is using a blueprint. Once the 'lang_code' is popped from the values dictionary and it will no longer be forwarded to the view function reducing the code to flask import Flask, g app = Flask(__name__) @app.url_defaults def add_language_code(endpoint, values): if 'lang_code' in values or not g.lang_code: return if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'): values['lang_code'] = g.lang_code @app.url_value_preprocessor def pull_lang_code(endpoint, values): g.lang_code = values.pop('lang_code', None) @app.route('/<lang_code>/') def index(): ... @app.route('/<lang_code>/about') def about(): ... Internationalized Blueprint URLs¶ Because blueprints can automatically prefix all URLs with a common string it’s easy to automatically do that for every function. Furthermore blueprints can have per-blueprint URL processors which removes a whole lot of logic from the url_defaults() function because it no longer has to check if the URL is really interested in a 'lang_code' flask import Blueprint, g bp = Blueprint('frontend', __name__, url_prefix='/<lang_code>') @bp.url_defaults def add_language_code(endpoint, values): values.setdefault('lang_code', g.lang_code) @bp.url_value_preprocessor def pull_lang_code(endpoint, values): g.lang_code = values.pop('lang_code') @bp.route('/') def index(): ... @bp.route('/about') def about(): ... Contents Using URL Processors Internationalized Application URLs Internationalized Blueprint URLs Navigation Overview Patterns for Flask Dispatching SQLite 3 with Flask Quick search\n\nExample:\n```text\nfrom flask import Flask, g\n\napp = Flask(__name__)\n\n@app.route('/<lang_code>/')\ndef index(lang_code):\n    g.lang_code = lang_code\n    ...\n\n@app.route('/<lang_code>/about')\ndef about(lang_code):\n    g.lang_code = lang_code\n    ...\n```\n\nExample:\n```text\n@app.url_defaults\ndef add_language_code(endpoint, values):\n    if 'lang_code' in values or not g.lang_code:\n        return\n    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):\n        values['lang_code'] = g.lang_code\n```\n\nExample:\n```text\n@app.url_value_preprocessor\ndef pull_lang_code(endpoint, values):\n    g.lang_code = values.pop('lang_code', None)\n```\n\nExample:\n```text\nfrom flask import Flask, g\n\napp = Flask(__name__)\n\n@app.url_defaults\ndef add_language_code(endpoint, values):\n    if 'lang_code' in values or not g.lang_code:\n        return\n    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):\n        values['lang_code'] = g.lang_code\n\n@app.url_value_preprocessor\ndef pull_lang_code(endpoint, values):\n    g.lang_code = values.pop('lang_code', None)\n\n@app.route('/<lang_code>/')\ndef index():\n    ...\n\n@app.route('/<lang_code>/about')\ndef about():\n    ...\n```\n\nExample:\n```text\nfrom flask import Blueprint, g\n\nbp = Blueprint('frontend', __name__, url_prefix='/<lang_code>')\n\n@bp.url_defaults\ndef add_language_code(endpoint, values):\n    values.setdefault('lang_code', g.lang_code)\n\n@bp.url_value_preprocessor\ndef pull_lang_code(endpoint, values):\n    g.lang_code = values.pop('lang_code')\n\n@bp.route('/')\ndef index():\n    ...\n\n@bp.route('/about')\ndef about():\n    ...\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.094Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":5,"totalLines":86,"estimatedTokens":1370}}55{"id":"doc-javascript_fetch_and_json_flask_documentation_3_-cd13e5e9","source":"documentation","title":"JavaScript, fetch, and JSON — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/javascript/","text":"JavaScript, fetch, and JSON¶ You may want to make your HTML page dynamic, by changing data without reloading the entire page. Instead of submitting an HTML <form> and performing a redirect to re-render the template, you can add JavaScript that calls fetch() and replaces content on the page. fetch() is the modern, built-in JavaScript solution to making requests from a page. You may have heard of other “AJAX” methods and libraries, such as XMLHttpRequest() or jQuery. These are no longer needed in modern browsers, although you may choose to use them or another library depending on your application’s requirements. These docs will only focus on built-in JavaScript features. Rendering Templates¶ It is important to understand the difference between templates and JavaScript. Templates are rendered on the server, before the response is sent to the user’s browser. JavaScript runs in the user’s browser, after the template is rendered and sent. Therefore, it is impossible to use JavaScript to affect how the Jinja template is rendered, but it is possible to render data into the JavaScript that will run. To provide data to JavaScript when rendering the template, use the tojson() filter in a <script> block. This will convert the data to a valid JavaScript object, and ensure that any unsafe HTML characters are rendered safely. If you do not use the tojson filter, you will get a SyntaxError in the browser console. data = generate_report() return render_template(\"report.html\", chart_data=data) <script> const chart_data = {{ chart_data|tojson }} chartLib.makeChart(chart_data) </script> A less common pattern is to add the data to a data- attribute on an HTML tag. In this case, you must use single quotes around the value, not double quotes, otherwise you will produce invalid or unsafe HTML. <div data-chart='{{ chart_data|tojson }}'></div> Generating URLs¶ The other way to get data from the server to JavaScript is to make a request for it. First, you need to know the URL to request. The simplest way to generate URLs is to continue to use url_for() when rendering the template. For user_url = {{ url_for(\"user\", id=current_user.id)|tojson }} fetch(user_url).then(...) However, you might need to generate a URL based on information you only know in JavaScript. As discussed above, JavaScript runs in the user’s browser, not as part of the template rendering, so you can’t use url_for at that point. In this case, you need to know the “root URL” under which your application is served. In simple setups, this is /, but it might also be something else, like https://example.com/myapp/. A simple way to tell your JavaScript code about this root is to set it as a global variable when rendering the template. Then you can use it when generating URLs from JavaScript. const SCRIPT_ROOT = {{ request.script_root|tojson }} let user_id = ... // do something to get a user id from the page let user_url = `${SCRIPT_ROOT}/user/${user_id}` fetch(user_url).then(...) Making a Request with fetch¶ fetch() takes two arguments, a URL and an object with other options, and returns a Promise. We won’t cover all the available options, and will only use then() on the promise, not other callbacks or await syntax. Read the linked MDN docs for more information about those features. By default, the GET method is used. If the response contains JSON, it can be used with a then() callback chain. const room_url = {{ url_for(\"room_detail\", id=room.id)|tojson }} fetch(room_url) ) To send data, use a data method such as POST, and pass the body option. The most common types for data are form data or JSON data. To send form data, pass a populated FormData object. This uses the same format as an HTML form, and would be accessed with request.form in a Flask view. let data = new FormData() data.append(\"name\", \"Flask Room\") data.append(\"description\", \"Talk about Flask here.\") fetch(room_url, { \"method\": \"POST\", \"body\": data, }).then(...) In general, prefer sending request data as form data, as would be used when submitting an HTML form. JSON can represent more complex data, but unless you need that it’s better to stick with the simpler format. When sending JSON data, the /json header must be sent as well, otherwise Flask will return a 415 Unsupported Media Type error. let data = { \"name\": \"Flask Room\", \"description\": \"Talk about Flask here.\", } fetch(room_url, { \"method\": \"POST\", \"headers\": {\"Content-Type\": \"application/json\"}, \"body\": JSON.stringify(data), }).then(...) Following Redirects¶ A response might be a redirect, for example if you logged in with JavaScript instead of a traditional HTML form, and your view returned a redirect instead of JSON. JavaScript requests do follow redirects, but they don’t change the page. If you want to make the page change you can inspect the response and apply the redirect manually. fetch(\"/login\", {\"body\": ...}).then( response => { if (response.redirected) { window.location = response.url } else { showLoginError() } } ) Replacing Content¶ A response might be new HTML, either a new section of the page to add or replace, or an entirely new page. In general, if you’re returning the entire page, it would be better to handle that with a redirect as shown in the previous section. The following example shows how to replace a <div> with the HTML returned by a request. <div id=\"geology-fact\"> {{ include \"geology_fact.html\" }} </div> <script> const geology_url = {{ url_for(\"geology_fact\")|tojson }} const geology_div = getElementById(\"geology-fact\") fetch(geology_url) If you want to return another JSON type, use the jsonify() function, which creates a response object with the given data serialized to JSON. from flask import jsonify @app.route(\"/users\") def user_list(): users = User.query.order_by(User.name).all() return jsonify([u.to_json() for u in users]) It is usually not a good idea to return file data in a JSON response. JSON cannot represent binary data directly, so it must be base64 encoded, which can be slow, takes more bandwidth to send, and is not as easy to cache. Instead, serve files using one view, and generate a URL to the desired file to include in the JSON. Then the client can make a separate request to get the linked resource after getting the JSON. Receiving JSON in Views¶ Use the json property of the request object to decode the request’s body as JSON. If the body is not valid JSON, a 400 Bad Request error will be raised. If the Content-Type header is not set to application/json, a 415 Unsupported Media Type error will be raised. from flask import request @app.post(\"/user/<int:id>\") def user_update(id): user = User.query.get_or_404(id) user.update_from_json(request.json) db.session.commit() return user.to_json() Contents JavaScript, fetch, and JSON Rendering Templates Generating URLs Making a Request with fetch Following Redirects Replacing Content Return JSON from Views Receiving JSON in Views Navigation Overview Patterns for Flask Flashing Loading Views Quick search\n\nExample:\n```text\ndata = generate_report()\nreturn render_template(\"report.html\", chart_data=data)\n```\n\nExample:\n```text\n<script>\n    const chart_data = {{ chart_data|tojson }}\n    chartLib.makeChart(chart_data)\n</script>\n```\n\nExample:\n```text\nconst user_url = {{ url_for(\"user\", id=current_user.id)|tojson }}\nfetch(user_url).then(...)\n```\n\nExample:\n```text\nconst SCRIPT_ROOT = {{ request.script_root|tojson }}\nlet user_id = ...  // do something to get a user id from the page\nlet user_url = `${SCRIPT_ROOT}/user/${user_id}`\nfetch(user_url).then(...)\n```\n\nExample:\n```text\nconst room_url = {{ url_for(\"room_detail\", id=room.id)|tojson }}\nfetch(room_url)\n    .then(response => response.json())\n    .then(data => {\n        // data is a parsed JSON object\n    })\n```\n\nExample:\n```text\nlet data = new FormData()\ndata.append(\"name\", \"Flask Room\")\ndata.append(\"description\", \"Talk about Flask here.\")\nfetch(room_url, {\n    \"method\": \"POST\",\n    \"body\": data,\n}).then(...)\n```\n\nExample:\n```text\nlet data = {\n    \"name\": \"Flask Room\",\n    \"description\": \"Talk about Flask here.\",\n}\nfetch(room_url, {\n    \"method\": \"POST\",\n    \"headers\": {\"Content-Type\": \"application/json\"},\n    \"body\": JSON.stringify(data),\n}).then(...)\n```\n\nExample:\n```text\nfetch(\"/login\", {\"body\": ...}).then(\n    response => {\n        if (response.redirected) {\n            window.location = response.url\n        } else {\n            showLoginError()\n        }\n    }\n)\n```\n\nExample:\n```text\n<div id=\"geology-fact\">\n    {{ include \"geology_fact.html\" }}\n</div>\n<script>\n    const geology_url = {{ url_for(\"geology_fact\")|tojson }}\n    const geology_div = getElementById(\"geology-fact\")\n    fetch(geology_url)\n        .then(response => response.text)\n        .then(text => geology_div.innerHTML = text)\n</script>\n```\n\nExample:\n```text\n@app.route(\"/user/<int:id>\")\ndef user_detail(id):\n    user = User.query.get_or_404(id)\n    return {\n        \"username\": User.username,\n        \"email\": User.email,\n        \"picture\": url_for(\"static\", filename=f\"users/{id}/profile.png\"),\n    }\n```\n\nExample:\n```text\nfrom flask import jsonify\n\n@app.route(\"/users\")\ndef user_list():\n    users = User.query.order_by(User.name).all()\n    return jsonify([u.to_json() for u in users])\n```\n\nExample:\n```text\nfrom flask import request\n\n@app.post(\"/user/<int:id>\")\ndef user_update(id):\n    user = User.query.get_or_404(id)\n    user.update_from_json(request.json)\n    db.session.commit()\n    return user.to_json()\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.096Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":126,"estimatedTokens":2359}}56{"id":"doc-sqlalchemy_in_flask_flask_documentation_3_1_x-9d6473c2","source":"documentation","title":"SQLAlchemy in Flask — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/sqlalchemy/","text":"SQLAlchemy in Flask¶ Many people prefer SQLAlchemy for database access. In this case it’s encouraged to use a package instead of a module for your flask application and drop the models into a separate module (Large Applications as Packages). While that is not necessary, it makes a lot of sense. There are four very common ways to use SQLAlchemy. I will outline each of them Extension¶ Because SQLAlchemy is a common database abstraction layer and object relational mapper that requires a little bit of configuration effort, there is a Flask extension that handles that for you. This is recommended if you want to get started quickly. You can download Flask-SQLAlchemy from PyPI. Declarative¶ The declarative extension in SQLAlchemy is the most recent method of using SQLAlchemy. It allows you to define tables and models in one go, similar to how Django works. In addition to the following text I recommend the official documentation on the declarative extension. Here’s the example database.py module for your sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker, declarative_base engine = create_engine('sqlite:////tmp/test.db') db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() Base.query = db_session.query_property() def init_db(): # import all modules here that might define models so that # they will be registered properly on the metadata. Otherwise # you will have to import them first before calling init_db() import yourapplication.models Base.metadata.create_all(bind=engine) To define your models, just subclass the Base class that was created by the code above. If you are wondering why we don’t have to care about threads here (like we did in the SQLite3 example above with the g object): that’s because SQLAlchemy does that for us already with the scoped_session. To use SQLAlchemy in a declarative way with your application, you just have to put the following code into your application module. Flask will automatically remove database sessions at the end of the request or when the application shuts yourapplication.database import db_session @app.teardown_appcontext def shutdown_session(exception=None): db_session.remove() Here is an example model (put this into models.py, e.g.): from sqlalchemy import Column, Integer, String from yourapplication.database import Base class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50), unique=True) email = Column(String(120), unique=True) def __init__(self, name=None, email=None): self.name = name self.email = email def __repr__(self): return f'<User {self.name!r}>' To create the database you can use the init_db function: >>> from yourapplication.database import init_db >>> init_db() You can insert entries into the database like this: >>> from yourapplication.database import db_session >>> from yourapplication.models import User >>> u = User('admin', 'admin@localhost') >>> db_session.add(u) >>> db_session.commit() Querying is simple as well: >>> User.query.all() [<User 'admin'>] >>> User.query.filter(User.name == 'admin').first() <User 'admin'> Manual Object Relational Mapping¶ Manual object relational mapping has a few upsides and a few downsides versus the declarative approach from above. The main difference is that you define tables and classes separately and map them together. It’s more flexible but a little more to type. In general it works like the declarative approach, so make sure to also split up your application into multiple modules in a package. Here is an example database.py module for your sqlalchemy import create_engine, MetaData from sqlalchemy.orm import scoped_session, sessionmaker engine = create_engine('sqlite:////tmp/test.db') metadata = MetaData() db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) def init_db(): metadata.create_all(bind=engine) As in the declarative approach, you need to close the session after each request or application context shutdown. Put this into your application yourapplication.database import db_session @app.teardown_appcontext def shutdown_session(exception=None): db_session.remove() Here is an example table and model (put this into models.py): from sqlalchemy import Table, Column, Integer, String from sqlalchemy.orm import mapper from yourapplication.database import metadata, db_session class User(object): query = db_session.query_property() def __init__(self, name=None, email=None): self.name = name self.email = email def __repr__(self): return f'<User {self.name!r}>' users = Table('users', metadata, Column('id', Integer, primary_key=True), Column('name', String(50), unique=True), Column('email', String(120), unique=True) ) mapper(User, users) Querying and inserting works exactly the same as in the example above. SQL Abstraction Layer¶ If you just want to use the database system (and SQL) abstraction layer you basically only need the sqlalchemy import create_engine, MetaData, Table engine = create_engine('sqlite:////tmp/test.db') metadata = MetaData(bind=engine) Then you can either declare the tables in your code like in the examples above, or automatically load sqlalchemy import Table users = Table('users', metadata, autoload=True) To insert data you can use the insert method. We have to get a connection first so that we can use a transaction: >>> con = engine.connect() >>> con.execute(users.insert(), name='admin', email='admin@localhost') SQLAlchemy will automatically commit for us. To query your database, you use the engine directly or use a connection: >>> users.select(users.c.id == 1).execute().first() (1, 'admin', 'admin@localhost') These results are also dict-like tuples: >>> r = users.select(users.c.id == 1).execute().first() >>> r['name'] 'admin' You can also pass strings of SQL statements to the execute() method: >>> engine.execute('select * from users where id = :1', [1]).first() (1, 'admin', 'admin@localhost') For more information about SQLAlchemy, head over to the website. Contents SQLAlchemy in Flask Flask-SQLAlchemy Extension Declarative Manual Object Relational Mapping SQL Abstraction Layer Navigation Overview Patterns for Flask SQLite 3 with Flask Files Quick search\n\nExample:\n```text\nfrom sqlalchemy import create_engine\nfrom sqlalchemy.orm import scoped_session, sessionmaker, declarative_base\n\nengine = create_engine('sqlite:////tmp/test.db')\ndb_session = scoped_session(sessionmaker(autocommit=False,\n                                         autoflush=False,\n                                         bind=engine))\nBase = declarative_base()\nBase.query = db_session.query_property()\n\ndef init_db():\n    # import all modules here that might define models so that\n    # they will be registered properly on the metadata.  Otherwise\n    # you will have to import them first before calling init_db()\n    import yourapplication.models\n    Base.metadata.create_all(bind=engine)\n```\n\nExample:\n```text\nfrom yourapplication.database import db_session\n\n@app.teardown_appcontext\ndef shutdown_session(exception=None):\n    db_session.remove()\n```\n\nExample:\n```text\nfrom sqlalchemy import Column, Integer, String\nfrom yourapplication.database import Base\n\nclass User(Base):\n    __tablename__ = 'users'\n    id = Column(Integer, primary_key=True)\n    name = Column(String(50), unique=True)\n    email = Column(String(120), unique=True)\n\n    def __init__(self, name=None, email=None):\n        self.name = name\n        self.email = email\n\n    def __repr__(self):\n        return f'<User {self.name!r}>'\n```\n\nExample:\n```text\n>>> from yourapplication.database import init_db\n>>> init_db()\n```\n\nExample:\n```text\n>>> from yourapplication.database import db_session\n>>> from yourapplication.models import User\n>>> u = User('admin', 'admin@localhost')\n>>> db_session.add(u)\n>>> db_session.commit()\n```\n\nExample:\n```text\n>>> User.query.all()\n[<User 'admin'>]\n>>> User.query.filter(User.name == 'admin').first()\n<User 'admin'>\n```\n\nExample:\n```text\nfrom sqlalchemy import create_engine, MetaData\nfrom sqlalchemy.orm import scoped_session, sessionmaker\n\nengine = create_engine('sqlite:////tmp/test.db')\nmetadata = MetaData()\ndb_session = scoped_session(sessionmaker(autocommit=False,\n                                         autoflush=False,\n                                         bind=engine))\ndef init_db():\n    metadata.create_all(bind=engine)\n```\n\nExample:\n```text\nfrom sqlalchemy import Table, Column, Integer, String\nfrom sqlalchemy.orm import mapper\nfrom yourapplication.database import metadata, db_session\n\nclass User(object):\n    query = db_session.query_property()\n\n    def __init__(self, name=None, email=None):\n        self.name = name\n        self.email = email\n\n    def __repr__(self):\n        return f'<User {self.name!r}>'\n\nusers = Table('users', metadata,\n    Column('id', Integer, primary_key=True),\n    Column('name', String(50), unique=True),\n    Column('email', String(120), unique=True)\n)\nmapper(User, users)\n```\n\nExample:\n```text\nfrom sqlalchemy import create_engine, MetaData, Table\n\nengine = create_engine('sqlite:////tmp/test.db')\nmetadata = MetaData(bind=engine)\n```\n\nExample:\n```text\nfrom sqlalchemy import Table\n\nusers = Table('users', metadata, autoload=True)\n```\n\nExample:\n```text\n>>> con = engine.connect()\n>>> con.execute(users.insert(), name='admin', email='admin@localhost')\n```\n\nExample:\n```text\n>>> users.select(users.c.id == 1).execute().first()\n(1, 'admin', 'admin@localhost')\n```\n\nExample:\n```text\n>>> r = users.select(users.c.id == 1).execute().first()\n>>> r['name']\n'admin'\n```\n\nExample:\n```text\n>>> engine.execute('select * from users where id = :1', [1]).first()\n(1, 'admin', 'admin@localhost')\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.099Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":14,"totalLines":152,"estimatedTokens":2431}}57{"id":"doc-application_dispatching_flask_documentation_3_1_-68b8b3b5","source":"documentation","title":"Application Dispatching — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/appdispatch/","text":"Application Dispatching¶ Application dispatching is the process of combining multiple Flask applications on the WSGI level. You can combine not only Flask applications but any WSGI application. This would allow you to run a Django and a Flask application in the same interpreter side by side if you want. The usefulness of this depends on how the applications work internally. The fundamental difference from Large Applications as Packages is that in this case you are running the same or different Flask applications that are entirely isolated from each other. They run different configurations and are dispatched on the WSGI level. Working with this Document¶ Each of the techniques and examples below results in an application object that can be run with any WSGI server. For development, use the flask run command to start a development server. For production, see Deploying to Production. from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' Combining Applications¶ If you have entirely separated applications and you want them to work next to each other in the same Python interpreter process you can take advantage of the werkzeug.wsgi.DispatcherMiddleware. The idea here is that each Flask application is a valid WSGI application and they are combined by the dispatcher middleware into a larger one that is dispatched based on prefix. For example you could have your main application run on / and your backend interface on /backend. from werkzeug.middleware.dispatcher import DispatcherMiddleware from frontend_app import application as frontend from backend_app import application as backend application = DispatcherMiddleware(frontend, { '/backend': backend }) Dispatch by Subdomain¶ Sometimes you might want to use multiple instances of the same application with different configurations. Assuming the application is created inside a function and you can call that function to instantiate it, that is really easy to implement. In order to develop your application to support creating new instances in functions have a look at the Application Factories pattern. A very common example would be creating applications per subdomain. For instance you configure your webserver to dispatch all requests for all subdomains to your application and you then use the subdomain information to create user-specific instances. Once you have your server set up to listen on all subdomains you can use a very simple WSGI application to do the dynamic application creation. The perfect level for abstraction in that regard is the WSGI layer. You write your own WSGI application that looks at the request that comes and delegates it to your Flask application. If that application does not exist yet, it is dynamically created and remembered. from threading import Lock class __init__(self, domain, create_app): self.domain = domain self.create_app = create_app self.lock = Lock() self.instances = {} def get_application(self, host): host = host.split(':')[0] assert host.endswith(self.domain), 'Configuration error' subdomain = host[:-len(self.domain)].rstrip('.') with self.lock: app = self.instances.get(subdomain) if app is = self.create_app(subdomain) self.instances[subdomain] = app return app def __call__(self, environ, start_response): app = self.get_application(environ['HTTP_HOST']) return app(environ, start_response) This dispatcher can then be used like myapplication import create_app, get_user_for_subdomain from werkzeug.exceptions import NotFound def make_app(subdomain): user = get_user_for_subdomain(subdomain) if user is None: # if there is no user for that subdomain we still have # to return a WSGI application that handles that request. # We can then just return the NotFound() exception as # application which will render a default 404 page. # You might also redirect the user to the main page then return NotFound() # otherwise create the application for the specific user return create_app(user) application = SubdomainDispatcher('example.com', make_app) Dispatch by Path¶ Dispatching by a path on the URL is very similar. Instead of looking at the Host header to figure out the subdomain one simply looks at the request path up to the first slash. from threading import Lock from wsgiref.util import shift_path_info class __init__(self, default_app, create_app): self.default_app = default_app self.create_app = create_app self.lock = Lock() self.instances = {} def get_application(self, prefix): with self.lock: app = self.instances.get(prefix) if app is = self.create_app(prefix) if app is not [prefix] = app return app def __call__(self, environ, start_response): app = self.get_application(_peek_path_info(environ)) if app is not (environ) = self.default_app return app(environ, start_response) def _peek_path_info(environ): segments = environ.get(\"PATH_INFO\", \"\").lstrip(\"/\").split(\"/\", 1) if segments[0] return None The big difference between this and the subdomain one is that this one falls back to another application if the creator function returns None. from myapplication import create_app, default_app, get_user_for_prefix def make_app(prefix): user = get_user_for_prefix(prefix) if user is not create_app(user) application = PathDispatcher(default_app, make_app) Contents Application Dispatching Working with this Document Combining Applications Dispatch by Subdomain Dispatch by Path Navigation Overview Patterns for Flask Factories URL Processors Quick search\n\nExample:\n```text\nfrom flask import Flask\n\napp = Flask(__name__)\n\n@app.route('/')\ndef hello_world():\n    return 'Hello World!'\n```\n\nExample:\n```text\nfrom werkzeug.middleware.dispatcher import DispatcherMiddleware\nfrom frontend_app import application as frontend\nfrom backend_app import application as backend\n\napplication = DispatcherMiddleware(frontend, {\n    '/backend': backend\n})\n```\n\nExample:\n```text\nfrom threading import Lock\n\nclass SubdomainDispatcher:\n\n    def __init__(self, domain, create_app):\n        self.domain = domain\n        self.create_app = create_app\n        self.lock = Lock()\n        self.instances = {}\n\n    def get_application(self, host):\n        host = host.split(':')[0]\n        assert host.endswith(self.domain), 'Configuration error'\n        subdomain = host[:-len(self.domain)].rstrip('.')\n        with self.lock:\n            app = self.instances.get(subdomain)\n            if app is None:\n                app = self.create_app(subdomain)\n                self.instances[subdomain] = app\n            return app\n\n    def __call__(self, environ, start_response):\n        app = self.get_application(environ['HTTP_HOST'])\n        return app(environ, start_response)\n```\n\nExample:\n```text\nfrom myapplication import create_app, get_user_for_subdomain\nfrom werkzeug.exceptions import NotFound\n\ndef make_app(subdomain):\n    user = get_user_for_subdomain(subdomain)\n    if user is None:\n        # if there is no user for that subdomain we still have\n        # to return a WSGI application that handles that request.\n        # We can then just return the NotFound() exception as\n        # application which will render a default 404 page.\n        # You might also redirect the user to the main page then\n        return NotFound()\n\n    # otherwise create the application for the specific user\n    return create_app(user)\n\napplication = SubdomainDispatcher('example.com', make_app)\n```\n\nExample:\n```text\nfrom threading import Lock\nfrom wsgiref.util import shift_path_info\n\nclass PathDispatcher:\n\n    def __init__(self, default_app, create_app):\n        self.default_app = default_app\n        self.create_app = create_app\n        self.lock = Lock()\n        self.instances = {}\n\n    def get_application(self, prefix):\n        with self.lock:\n            app = self.instances.get(prefix)\n            if app is None:\n                app = self.create_app(prefix)\n                if app is not None:\n                    self.instances[prefix] = app\n            return app\n\n    def __call__(self, environ, start_response):\n        app = self.get_application(_peek_path_info(environ))\n        if app is not None:\n            shift_path_info(environ)\n        else:\n            app = self.default_app\n        return app(environ, start_response)\n\ndef _peek_path_info(environ):\n    segments = environ.get(\"PATH_INFO\", \"\").lstrip(\"/\").split(\"/\", 1)\n    if segments:\n        return segments[0]\n\n    return None\n```\n\nExample:\n```text\nfrom myapplication import create_app, default_app, get_user_for_prefix\n\ndef make_app(prefix):\n    user = get_user_for_prefix(prefix)\n    if user is not None:\n        return create_app(user)\n\napplication = PathDispatcher(default_app, make_app)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.099Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":6,"totalLines":124,"estimatedTokens":2161}}58{"id":"doc-form_validation_with_wtforms_flask_documentation-f3f86950","source":"documentation","title":"Form Validation with WTForms — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/wtforms/","text":"Form Validation with WTForms¶ When you have to work with form data submitted by a browser view, code quickly becomes very hard to read. There are libraries out there designed to make this process easier to manage. One of them is WTForms which we will handle here. If you find yourself in the situation of having many forms, you might want to give it a try. When you are working with WTForms you have to define your forms as classes first. I recommend breaking up the application into multiple modules (Large Applications as Packages) for that and adding a separate module for the forms. Getting the most out of WTForms with an Extension The Flask-WTF extension expands on this pattern and adds a few little helpers that make working with forms and Flask more fun. You can get it from PyPI. The Forms¶ This is an example form for a typical registration wtforms import Form, BooleanField, StringField, PasswordField, validators class RegistrationForm(Form): username = StringField('Username', [validators.Length(min=4, max=25)]) email = StringField('Email Address', [validators.Length(min=6, max=35)]) password = PasswordField('New Password', [ validators.DataRequired(), validators.EqualTo('confirm', message='Passwords must match') ]) confirm = PasswordField('Repeat Password') accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()]) In the View¶ In the view function, the usage of this form looks like this: @app.route('/register', methods=['GET', 'POST']) def register(): form = RegistrationForm(request.form) if request.method == 'POST' and form.validate(): user = User(form.username.data, form.email.data, form.password.data) db_session.add(user) flash('Thanks for registering') return redirect(url_for('login')) return render_template('register.html', form=form) Notice we’re implying that the view is using SQLAlchemy here (SQLAlchemy in Flask), but that’s not a requirement, of course. Adapt the code as necessary. Things to the form from the request form value if the data is submitted via the HTTP POST method and args if the data is submitted as GET. to validate the data, call the validate() method, which will return True if the data validates, False otherwise. to access individual values from the form, access form.<NAME>.data. Forms in Templates¶ Now to the template side. When you pass the form to the templates, you can easily render them there. Look at the following example template to see how easy this is. WTForms does half the form generation for us already. To make it even nicer, we can write a macro that renders a field with label and a list of errors if there are any. Here’s an example _formhelpers.html template with such a macro: {% macro render_field(field) %} <dt>{{ field.label }} <dd>{{ field(**kwargs)|safe }} {% if field.errors %} <ul class=errors> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </dd> {% endmacro %} This macro accepts a couple of keyword arguments that are forwarded to WTForm’s field function, which renders the field for us. The keyword arguments will be inserted as HTML attributes. So, for example, you can call render_field(form.username, class='username') to add a class to the input element. Note that WTForms returns standard Python strings, so we have to tell Jinja that this data is already HTML-escaped with the |safe filter. Here is the register.html template for the function we used above, which takes advantage of the _formhelpers.html template: {% from \"_formhelpers.html\" import render_field %} <form method=post> <dl> {{ render_field(form.username) }} {{ render_field(form.email) }} {{ render_field(form.password) }} {{ render_field(form.confirm) }} {{ render_field(form.accept_tos) }} </dl> <p><input type=submit value=Register> </form> For more information about WTForms, head over to the WTForms website. Contents Form Validation with WTForms The Forms In the View Forms in Templates Navigation Overview Patterns for Flask Decorators Inheritance Quick search\n\nExample:\n```text\nfrom wtforms import Form, BooleanField, StringField, PasswordField, validators\n\nclass RegistrationForm(Form):\n    username = StringField('Username', [validators.Length(min=4, max=25)])\n    email = StringField('Email Address', [validators.Length(min=6, max=35)])\n    password = PasswordField('New Password', [\n        validators.DataRequired(),\n        validators.EqualTo('confirm', message='Passwords must match')\n    ])\n    confirm = PasswordField('Repeat Password')\n    accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])\n```\n\nExample:\n```text\n@app.route('/register', methods=['GET', 'POST'])\ndef register():\n    form = RegistrationForm(request.form)\n    if request.method == 'POST' and form.validate():\n        user = User(form.username.data, form.email.data,\n                    form.password.data)\n        db_session.add(user)\n        flash('Thanks for registering')\n        return redirect(url_for('login'))\n    return render_template('register.html', form=form)\n```\n\nExample:\n```text\n{% macro render_field(field) %}\n  <dt>{{ field.label }}\n  <dd>{{ field(**kwargs)|safe }}\n  {% if field.errors %}\n    <ul class=errors>\n    {% for error in field.errors %}\n      <li>{{ error }}</li>\n    {% endfor %}\n    </ul>\n  {% endif %}\n  </dd>\n{% endmacro %}\n```\n\nExample:\n```text\n{% from \"_formhelpers.html\" import render_field %}\n<form method=post>\n  <dl>\n    {{ render_field(form.username) }}\n    {{ render_field(form.email) }}\n    {{ render_field(form.password) }}\n    {{ render_field(form.confirm) }}\n    {{ render_field(form.accept_tos) }}\n  </dl>\n  <p><input type=submit value=Register>\n</form>\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.100Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":63,"estimatedTokens":1411}}59{"id":"doc-message_flashing_flask_documentation_3_1_x-6b1fec08","source":"documentation","title":"Message Flashing — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/flashing/","text":"Example:\n```text\nfrom flask import Flask, flash, redirect, render_template, \\\n     request, url_for\n\napp = Flask(__name__)\napp.secret_key = b'_5#y2L\"F4Q8z\\n\\xec]/'\n\n@app.route('/')\ndef index():\n    return render_template('index.html')\n\n@app.route('/login', methods=['GET', 'POST'])\ndef login():\n    error = None\n    if request.method == 'POST':\n        if request.form['username'] != 'admin' or \\\n                request.form['password'] != 'secret':\n            error = 'Invalid credentials'\n        else:\n            flash('You were successfully logged in')\n            return redirect(url_for('index'))\n    return render_template('login.html', error=error)\n```\n\nExample:\n```text\n<!doctype html>\n<title>My Application</title>\n{% with messages = get_flashed_messages() %}\n  {% if messages %}\n    <ul class=flashes>\n    {% for message in messages %}\n      <li>{{ message }}</li>\n    {% endfor %}\n    </ul>\n  {% endif %}\n{% endwith %}\n{% block body %}{% endblock %}\n```\n\nExample:\n```text\n{% extends \"layout.html\" %}\n{% block body %}\n  <h1>Overview</h1>\n  <p>Do you want to <a href=\"{{ url_for('login') }}\">log in?</a>\n{% endblock %}\n```\n\nExample:\n```text\n{% extends \"layout.html\" %}\n{% block body %}\n  <h1>Login</h1>\n  {% if error %}\n    <p class=error><strong>Error:</strong> {{ error }}\n  {% endif %}\n  <form method=post>\n    <dl>\n      <dt>Username:\n      <dd><input type=text name=username value=\"{{\n          request.form.username }}\">\n      <dt>Password:\n      <dd><input type=password name=password>\n    </dl>\n    <p><input type=submit value=Login>\n  </form>\n{% endblock %}\n```\n\nExample:\n```text\nflash('Invalid password provided', 'error')\n```\n\nExample:\n```text\n{% with messages = get_flashed_messages(with_categories=true) %}\n  {% if messages %}\n    <ul class=flashes>\n    {% for category, message in messages %}\n      <li class=\"{{ category }}\">{{ message }}</li>\n    {% endfor %}\n    </ul>\n  {% endif %}\n{% endwith %}\n```\n\nExample:\n```text\n{% with errors = get_flashed_messages(category_filter=[\"error\"]) %}\n{% if errors %}\n<div class=\"alert-message block-message error\">\n  <a class=\"close\" href=\"#\">×</a>\n  <ul>\n    {%- for msg in errors %}\n    <li>{{ msg }}</li>\n    {% endfor -%}\n  </ul>\n</div>\n{% endif %}\n{% endwith %}\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.100Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":7,"totalLines":106,"estimatedTokens":563}}60{"id":"doc-deploying_to_production_flask_documentation_3_1_-43f177c4","source":"documentation","title":"Deploying to Production — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/deploying/","text":"Deploying to Production¶ After developing your application, you’ll want to make it available publicly to other users. When you’re developing locally, you’re probably using the built-in development server, debugger, and reloader. These should not be used in production. Instead, you should use a dedicated WSGI server or hosting platform, some of which will be described here. “Production” means “not development”, which applies whether you’re serving your application publicly to millions of users or privately / locally to a single user. Do not use the development server when deploying to production. It is intended for use only during local development. It is not designed to be particularly secure, stable, or efficient. Self-Hosted Options¶ Flask is a WSGI application. A WSGI server is used to run the application, converting incoming HTTP requests to the standard WSGI environ, and converting outgoing WSGI responses to HTTP responses. The primary goal of these docs is to familiarize you with the concepts involved in running a WSGI application using a production WSGI server and HTTP server. There are many WSGI servers and HTTP servers, with many configuration possibilities. The pages below discuss the most common servers, and show the basics of running each one. The next section discusses platforms that can manage this for you. Gunicorn Waitress mod_wsgi uWSGI gevent ASGI WSGI servers have HTTP servers built-in. However, a dedicated HTTP server may be safer, more efficient, or more capable. Putting an HTTP server in front of the WSGI server is called a “reverse proxy.” Tell Flask it is Behind a Proxy nginx Apache httpd This list is not exhaustive, and you should evaluate these and other servers based on your application’s needs. Different servers will have different capabilities, configuration, and support. Hosting Platforms¶ There are many services available for hosting web applications without needing to maintain your own server, networking, domain, etc. Some services may have a free tier up to a certain time or bandwidth. Many of these services use one of the WSGI servers described above, or a similar interface. The links below are for some of the most common platforms, which have instructions for Flask, WSGI, or Python. PythonAnywhere Google App Engine Google Cloud Run AWS Elastic Beanstalk Microsoft Azure This list is not exhaustive, and you should evaluate these and other services based on your application’s needs. Different services will have different capabilities, configuration, pricing, and support. You’ll probably need to Tell Flask it is Behind a Proxy when using most hosting platforms. Contents Deploying to Production Self-Hosted Options Hosting Platforms Navigation Overview Considerations Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.101Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":693}}61{"id":"doc-contributing_flask_documentation_3_1_x-9b39071f","source":"documentation","title":"Contributing — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/contributing/","text":"Contributing¶ See the Pallets detailed contributing documentation for many ways to contribute, including reporting issues, requesting features, asking or answering questions, and making PRs. Navigation Overview Extension Development License Quick search\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.101Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":0,"totalLines":3,"estimatedTokens":67}}62{"id":"doc-using_sqlite_3_with_flask_flask_documentation_3_-41f0f6d8","source":"documentation","title":"Using SQLite 3 with Flask — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/sqlite3/","text":"Using SQLite 3 with Flask¶ In Flask you can easily implement the opening of database connections on demand and closing them when the context dies (usually at the end of the request). Here is a simple example of how you can use SQLite 3 with sqlite3 from flask import g DATABASE = '/path/to/database.db' def get_db(): db = getattr(g, '_database', None) if db is = g._database = sqlite3.connect(DATABASE) return db @app.teardown_appcontext def close_connection(exception): db = getattr(g, '_database', None) if db is not () Now, to use the database, the application must either have an active application context (which is always true if there is a request in flight) or create an application context itself. At that point the get_db function can be used to get the current database connection. Whenever the context is destroyed the database connection will be terminated. Example: @app.route('/') def index(): cur = get_db().cursor() ... Note Please keep in mind that the teardown request and appcontext functions are always executed, even if a before-request handler failed or was never executed. Because of this we have to make sure here that the database is there before we close it. Connect on Demand¶ The upside of this approach (connecting on first use) is that this will only open the connection if truly necessary. If you want to use this code outside a request context you can use it in a Python shell by opening the application context by app.app_context(): # now you can use get_db() Easy Querying¶ Now in each request handling function you can access get_db() to get the current open database connection. To simplify working with SQLite, a row factory function is useful. It is executed for every result returned from the database to convert the result. For instance, in order to get dictionaries instead of tuples, this could be inserted into the get_db function we created make_dicts(cursor, row): return dict((cursor.description[idx][0], value) for idx, value in enumerate(row)) db.row_factory = make_dicts This will make the sqlite3 module return dicts for this database connection, which are much nicer to deal with. Even more simply, we could place this in get_db = sqlite3.Row This would use Row objects rather than dicts to return the results of queries. These are namedtuple s, so we can access them either by index or by key. For example, assuming we have a sqlite3.Row called r for the rows id, FirstName, LastName, and MiddleInitial: >>> # You can get values based on the row's name >>> r['FirstName'] John >>> # Or, you can get them based on index >>> r[1] John # Row objects are also iterable: >>> for value in print(value) 1 John Doe M Additionally, it is a good idea to provide a query function that combines getting the cursor, executing and fetching the query_db(query, args=(), one=False): cur = get_db().execute(query, args) rv = cur.fetchall() cur.close() return (rv[0] if rv else None) if one else rv This handy little function, in combination with a row factory, makes working with the database much more pleasant than it is by just using the raw cursor and connection objects. Here is how you can use user in query_db('select * from users'): print(user['username'], 'has the id', user['user_id']) Or if you just want a single = query_db('select * from users where username = ?', [the_username], one=True) if user is ('No such user') (the_username, 'has the id', user['user_id']) To pass variable parts to the SQL statement, use a question mark in the statement and pass in the arguments as a list. Never directly add them to the SQL statement with string formatting because this makes it possible to attack the application using SQL Injections. Initial Schemas¶ Relational databases need schemas, so applications often ship a schema.sql file that creates the database. It’s a good idea to provide a function that creates the database based on that schema. This function can do that for init_db(): with app.app_context(): db = get_db() with app.open_resource('schema.sql', mode='r') as ().executescript(f.read()) db.commit() You can then create such a database from the Python shell: >>> from yourapplication import init_db >>> init_db() Contents Using SQLite 3 with Flask Connect on Demand Easy Querying Initial Schemas Navigation Overview Patterns for Flask URL Processors in Flask Quick search\n\nExample:\n```text\nimport sqlite3\nfrom flask import g\n\nDATABASE = '/path/to/database.db'\n\ndef get_db():\n    db = getattr(g, '_database', None)\n    if db is None:\n        db = g._database = sqlite3.connect(DATABASE)\n    return db\n\n@app.teardown_appcontext\ndef close_connection(exception):\n    db = getattr(g, '_database', None)\n    if db is not None:\n        db.close()\n```\n\nExample:\n```text\n@app.route('/')\ndef index():\n    cur = get_db().cursor()\n    ...\n```\n\nExample:\n```text\nwith app.app_context():\n    # now you can use get_db()\n```\n\nExample:\n```text\ndef make_dicts(cursor, row):\n    return dict((cursor.description[idx][0], value)\n                for idx, value in enumerate(row))\n\ndb.row_factory = make_dicts\n```\n\nExample:\n```text\ndb.row_factory = sqlite3.Row\n```\n\nExample:\n```text\n>>> # You can get values based on the row's name\n>>> r['FirstName']\nJohn\n>>> # Or, you can get them based on index\n>>> r[1]\nJohn\n# Row objects are also iterable:\n>>> for value in r:\n...     print(value)\n1\nJohn\nDoe\nM\n```\n\nExample:\n```text\ndef query_db(query, args=(), one=False):\n    cur = get_db().execute(query, args)\n    rv = cur.fetchall()\n    cur.close()\n    return (rv[0] if rv else None) if one else rv\n```\n\nExample:\n```text\nfor user in query_db('select * from users'):\n    print(user['username'], 'has the id', user['user_id'])\n```\n\nExample:\n```text\nuser = query_db('select * from users where username = ?',\n                [the_username], one=True)\nif user is None:\n    print('No such user')\nelse:\n    print(the_username, 'has the id', user['user_id'])\n```\n\nExample:\n```text\ndef init_db():\n    with app.app_context():\n        db = get_db()\n        with app.open_resource('schema.sql', mode='r') as f:\n            db.cursor().executescript(f.read())\n        db.commit()\n```\n\nExample:\n```text\n>>> from yourapplication import init_db\n>>> init_db()\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.101Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":11,"totalLines":109,"estimatedTokens":1547}}63{"id":"doc-uploading_files_flask_documentation_3_1_x-bc3402c2","source":"documentation","title":"Uploading Files — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/fileuploads/","text":"Uploading Files¶ Ah yes, the good old problem of file uploads. The basic idea of file uploads is actually quite simple. It basically works like <form> tag is marked with enctype=multipart/form-data and an <input type=file> is placed in that form. The application accesses the file from the files dictionary on the request object. use the save() method of the file to save the file permanently somewhere on the filesystem. A Gentle Introduction¶ Let’s start with a very basic application that uploads a file to a specific upload folder and displays a file to the user. Let’s look at the bootstrapping code for our os from flask import Flask, flash, request, redirect, url_for from werkzeug.utils import secure_filename UPLOAD_FOLDER = '/path/to/the/uploads' ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'} app = Flask(__name__) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER So first we need a couple of imports. Most should be straightforward, the werkzeug.secure_filename() is explained a little bit later. The UPLOAD_FOLDER is where we will store the uploaded files and the ALLOWED_EXTENSIONS is the set of allowed file extensions. Why do we limit the extensions that are allowed? You probably don’t want your users to be able to upload everything there if the server is directly sending out the data to the client. That way you can make sure that users are not able to upload HTML files that would cause XSS problems (see Cross-Site Scripting (XSS)). Also make sure to disallow .php files if the server executes them, but who has PHP installed on their server, right? :) Next the functions that check if an extension is valid and that uploads the file and redirects the user to the URL for the uploaded allowed_file(filename): return '.' in filename and \\ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': # check if the post request has the file part if 'file' not in request.files: flash('No file part') return redirect(request.url) file = request.files['file'] # If the user does not select a file, the browser submits an # empty file without a filename. if file.filename == '': flash('No selected file') return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return redirect(url_for('download_file', name=filename)) return ''' <!doctype html> <title>Upload new File</title> <h1>Upload new File</h1> <form method=post enctype=multipart/form-data> <input type=file name=file> <input type=submit value=Upload> </form> ''' So what does that secure_filename() function actually do? Now the problem is that there is that principle called “never trust user input”. This is also true for the filename of an uploaded file. All submitted form data can be forged, and filenames can be dangerous. For the moment just use that function to secure a filename before storing it directly on the filesystem. Information for the Pros So you’re interested in what that secure_filename() function does and what the problem is if you’re not using it? So just imagine someone would send the following information as filename to your = \"../../../../home/username/.bashrc\" Assuming the number of ../ is correct and you would join this with the UPLOAD_FOLDER the user might have the ability to modify a file on the server’s filesystem he or she should not modify. This does require some knowledge about how the application looks like, but trust me, hackers are patient :) Now let’s look how that function works: >>> secure_filename('../../../../home/username/.bashrc') 'home_username_.bashrc' We want to be able to serve the uploaded files so they can be downloaded by users. We’ll define a download_file view to serve files in the upload folder by name. url_for(\"download_file\", name=name) generates download URLs. from flask import send_from_directory @app.route('/uploads/<name>') def download_file(name): return send_from_directory(app.config[\"UPLOAD_FOLDER\"], name) If you’re using middleware or the HTTP server to serve files, you can register the download_file endpoint as build_only so url_for will work without a view function. app.add_url_rule( \"/uploads/<name>\", endpoint=\"download_file\", build_only=True ) Improving Uploads¶ Changelog Added in version 0.6. So how exactly does Flask handle uploads? Well it will store them in the webserver’s memory if the files are reasonably small, otherwise in a temporary location (as returned by tempfile.gettempdir()). But how do you specify the maximum file size after which an upload is aborted? By default Flask will happily accept file uploads with an unlimited amount of memory, but you can limit that by setting the MAX_CONTENT_LENGTH config flask import Flask, Request app = Flask(__name__) app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000 The code above will limit the maximum allowed payload to 16 megabytes. If a larger file is transmitted, Flask will raise a RequestEntityTooLarge exception. Connection Reset Issue When using the local development server, you may get a connection reset error instead of a 413 response. You will get the correct status response when running the app with a production WSGI server. This feature was added in Flask 0.6 but can be achieved in older versions as well by subclassing the request object. For more information on that consult the Werkzeug documentation on file handling. Upload Progress Bars¶ A while ago many developers had the idea to read the incoming file in small chunks and store the upload progress in the database to be able to poll the progress with JavaScript from the client. The client asks the server every 5 seconds how much it has transmitted, but this is something it should already know. An Easier Solution¶ Now there are better solutions that work faster and are more reliable. There are JavaScript libraries like jQuery that have form plugins to ease the construction of progress bar. Because the common pattern for file uploads exists almost unchanged in all applications dealing with uploads, there are also some Flask extensions that implement a full fledged upload mechanism that allows controlling which file extensions are allowed to be uploaded. Contents Uploading Files A Gentle Introduction Improving Uploads Upload Progress Bars An Easier Solution Navigation Overview Patterns for Flask in Flask Quick search\n\nExample:\n```text\nimport os\nfrom flask import Flask, flash, request, redirect, url_for\nfrom werkzeug.utils import secure_filename\n\nUPLOAD_FOLDER = '/path/to/the/uploads'\nALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}\n\napp = Flask(__name__)\napp.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER\n```\n\nExample:\n```text\ndef allowed_file(filename):\n    return '.' in filename and \\\n           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS\n\n@app.route('/', methods=['GET', 'POST'])\ndef upload_file():\n    if request.method == 'POST':\n        # check if the post request has the file part\n        if 'file' not in request.files:\n            flash('No file part')\n            return redirect(request.url)\n        file = request.files['file']\n        # If the user does not select a file, the browser submits an\n        # empty file without a filename.\n        if file.filename == '':\n            flash('No selected file')\n            return redirect(request.url)\n        if file and allowed_file(file.filename):\n            filename = secure_filename(file.filename)\n            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))\n            return redirect(url_for('download_file', name=filename))\n    return '''\n    <!doctype html>\n    <title>Upload new File</title>\n    <h1>Upload new File</h1>\n    <form method=post enctype=multipart/form-data>\n      <input type=file name=file>\n      <input type=submit value=Upload>\n    </form>\n    '''\n```\n\nExample:\n```text\nfilename = \"../../../../home/username/.bashrc\"\n```\n\nExample:\n```text\n>>> secure_filename('../../../../home/username/.bashrc')\n'home_username_.bashrc'\n```\n\nExample:\n```text\nfrom flask import send_from_directory\n\n@app.route('/uploads/<name>')\ndef download_file(name):\n    return send_from_directory(app.config[\"UPLOAD_FOLDER\"], name)\n```\n\nExample:\n```text\napp.add_url_rule(\n    \"/uploads/<name>\", endpoint=\"download_file\", build_only=True\n)\n```\n\nExample:\n```text\nfrom flask import Flask, Request\n\napp = Flask(__name__)\napp.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.102Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":7,"totalLines":85,"estimatedTokens":2132}}64{"id":"doc-subclassing_flask_flask_documentation_3_1_x-6126a5c2","source":"documentation","title":"Subclassing Flask — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/subclassing/","text":"Subclassing Flask¶ The Flask class is designed for subclassing. For example, you may want to override how request parameters are handled to preserve their flask import Flask, Request from werkzeug.datastructures import ImmutableOrderedMultiDict class MyRequest(Request): \"\"\"Request subclass to override request parameter storage\"\"\" parameter_storage_class = ImmutableOrderedMultiDict class MyFlask(Flask): \"\"\"Flask subclass using the custom request class\"\"\" request_class = MyRequest This is the recommended approach for overriding or augmenting Flask’s internal functionality. Navigation Overview Patterns for Flask Tasks with Celery Applications Quick search\n\nExample:\n```text\nfrom flask import Flask, Request\nfrom werkzeug.datastructures import ImmutableOrderedMultiDict\nclass MyRequest(Request):\n    \"\"\"Request subclass to override request parameter storage\"\"\"\n    parameter_storage_class = ImmutableOrderedMultiDict\nclass MyFlask(Flask):\n    \"\"\"Flask subclass using the custom request class\"\"\"\n    request_class = MyRequest\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.104Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":1,"totalLines":15,"estimatedTokens":262}}65{"id":"doc-bsd_3_clause_license_flask_documentation_3_1_x-ad3bf463","source":"documentation","title":"BSD-3-Clause License — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/license/","text":"Example:\n```text\nCopyright 2010 Pallets\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n1.  Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n2.  Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n\n3.  Neither the name of the copyright holder nor the names of its\n    contributors may be used to endorse or promote products derived from\n    this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.104Z","totalSectionsIncluded":0,"totalCodeBlocksIncluded":1,"totalLines":33,"estimatedTokens":378}}66{"id":"doc-single_page_applications_flask_documentation_3_1-752da775","source":"documentation","title":"Single-Page Applications — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/singlepageapplications/","text":"Single-Page Applications¶ Flask can be used to serve Single-Page Applications (SPA) by placing static files produced by your frontend framework in a subfolder inside of your project. You will also need to create a catch-all endpoint that routes all requests to your SPA. The following example demonstrates how to serve an SPA along with an flask import Flask, jsonify app = Flask(__name__, static_folder='app', static_url_path=\"/app\") @app.route(\"/heartbeat\") def heartbeat(): return jsonify({\"status\": \"healthy\"}) @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def catch_all(path): return app.send_static_file(\"index.html\") Navigation Overview Patterns for Flask Flask Considerations Quick search\n\nExample:\n```text\nfrom flask import Flask, jsonify\n\napp = Flask(__name__, static_folder='app', static_url_path=\"/app\")\n\n\n@app.route(\"/heartbeat\")\ndef heartbeat():\n    return jsonify({\"status\": \"healthy\"})\n\n\n@app.route('/', defaults={'path': ''})\n@app.route('/<path:path>')\ndef catch_all(path):\n    return app.send_static_file(\"index.html\")\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.104Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":1,"totalLines":21,"estimatedTokens":269}}67{"id":"doc-streaming_contents_flask_documentation_3_1_x-c8a4ee4b","source":"documentation","title":"Streaming Contents — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/streaming/","text":"Streaming Contents¶ Sometimes you want to send an enormous amount of data to the client, much more than you want to keep in memory. When you are generating the data on the fly though, how do you send that back to the client without the roundtrip to the filesystem? The answer is by using generators and direct responses. HTTP Response Behavior¶ Headers cannot be changed after the streaming response starts. When using streaming, it’s important to be aware of the order than an HTTP response is sent. All headers must be sent first, then the body. More headers cannot be sent after the body has begun. Therefore, you must make sure all headers are set before starting the response, outside the generator. In particular, if the generator will access session, be sure to do so in the view as well so that the header will be set. Do not modify the session in the generator, as the Set-Cookie header will already be sent. Basic Usage¶ This is a basic view function that generates a lot of CSV data on the fly. The trick is to have an inner function that uses a generator to generate data and to then invoke that function and pass it to a response object: @app.route('/large.csv') def generate_large_csv(): def generate(): for row in iter_all_rows(): yield f\"{','.join(row)}\\n\" return generate(), {\"Content-Type\": \"text/csv\"} Each yield expression is directly sent to the browser. Note though that some WSGI middlewares might break streaming, so be careful there in debug environments with profilers and other things you might have enabled. Streaming from Templates¶ The Jinja template engine supports rendering a template piece by piece, returning an iterator of strings. Flask provides the stream_template() and stream_template_string() functions to make this easier to use. from flask import stream_template @app.get(\"/timeline\") def timeline(): return stream_template(\"timeline.html\") The parts yielded by the render stream tend to match statement blocks in the template. Streaming with Context¶ The request will not be active while the generator is running, because the view has already returned at that point. If you try to access request, you’ll get a RuntimeError. If your generator function relies on data in request, use the stream_with_context() wrapper. This will keep the request context active during the generator. from flask import stream_with_context, request from markupsafe import escape @app.route('/stream') def streamed_response(): def generate(): yield '<p>Hello ' yield escape(request.args['name']) yield '!</p>' return stream_with_context(generate()) It can also be used as a decorator. @stream_with_context def generate(): ... return generate() The stream_template() and stream_template_string() functions automatically use stream_with_context() if a request is active. Contents Streaming Contents HTTP Response Behavior Basic Usage Streaming from Templates Streaming with Context Navigation Overview Patterns for Flask a favicon Request Callbacks Quick search\n\nExample:\n```text\n@app.route('/large.csv')\ndef generate_large_csv():\n    def generate():\n        for row in iter_all_rows():\n            yield f\"{','.join(row)}\\n\"\n    return generate(), {\"Content-Type\": \"text/csv\"}\n```\n\nExample:\n```text\nfrom flask import stream_template\n\n@app.get(\"/timeline\")\ndef timeline():\n    return stream_template(\"timeline.html\")\n```\n\nExample:\n```text\nfrom flask import stream_with_context, request\nfrom markupsafe import escape\n\n@app.route('/stream')\ndef streamed_response():\n    def generate():\n        yield '<p>Hello '\n        yield escape(request.args['name'])\n        yield '!</p>'\n    return stream_with_context(generate())\n```\n\nExample:\n```text\n@stream_with_context\ndef generate():\n    ...\n\nreturn generate()\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.104Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":4,"totalLines":45,"estimatedTokens":936}}68{"id":"doc-adding_http_method_overrides_flask_documentation-0fa2b8be","source":"documentation","title":"Adding HTTP Method Overrides — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/methodoverrides/","text":"Adding HTTP Method Overrides¶ Some HTTP proxies do not support arbitrary HTTP methods or newer HTTP methods (such as PATCH). In that case it’s possible to “proxy” HTTP methods through another HTTP method in total violation of the protocol. The way this works is by letting the client do an HTTP POST request and set the X-HTTP-Method-Override header. Then the method is replaced with the header value before being passed to Flask. This can be accomplished with an HTTP HTTPMethodOverrideMiddleware(object): allowed_methods = frozenset([ 'GET', 'HEAD', 'POST', 'DELETE', 'PUT', 'PATCH', 'OPTIONS' ]) bodyless_methods = frozenset(['GET', 'HEAD', 'OPTIONS', 'DELETE']) def __init__(self, app): self.app = app def __call__(self, environ, start_response): method = environ.get('HTTP_X_HTTP_METHOD_OVERRIDE', '').upper() if method in self.allowed_methods: environ['REQUEST_METHOD'] = method if method in self.bodyless_methods: environ['CONTENT_LENGTH'] = '0' return self.app(environ, start_response) To use this with Flask, wrap the app object with the flask import Flask app = Flask(__name__) app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app) Navigation Overview Patterns for Flask Request Callbacks Content Checksums Quick search\n\nExample:\n```text\nclass HTTPMethodOverrideMiddleware(object):\n    allowed_methods = frozenset([\n        'GET',\n        'HEAD',\n        'POST',\n        'DELETE',\n        'PUT',\n        'PATCH',\n        'OPTIONS'\n    ])\n    bodyless_methods = frozenset(['GET', 'HEAD', 'OPTIONS', 'DELETE'])\n\n    def __init__(self, app):\n        self.app = app\n\n    def __call__(self, environ, start_response):\n        method = environ.get('HTTP_X_HTTP_METHOD_OVERRIDE', '').upper()\n        if method in self.allowed_methods:\n            environ['REQUEST_METHOD'] = method\n        if method in self.bodyless_methods:\n            environ['CONTENT_LENGTH'] = '0'\n        return self.app(environ, start_response)\n```\n\nExample:\n```text\nfrom flask import Flask\n\napp = Flask(__name__)\napp.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.104Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":37,"estimatedTokens":518}}69{"id":"doc-using_async_and_await_flask_documentation_3_1_x-ea1090a1","source":"documentation","title":"Using async and await — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/async-await/","text":"Using async and await¶ Changelog Added in version 2.0. Routes, error handlers, before request, after request, and teardown functions can all be coroutine functions if Flask is installed with the async extra (pip install flask[async]). This allows views to be defined with async def and use await. @app.route(\"/get-data\") async def get_data(): data = await async_db_query(...) return jsonify(data) Pluggable class-based views also support handlers that are implemented as coroutines. This applies to the dispatch_request() method in views that inherit from the flask.views.View class, as well as all the HTTP method handlers in views that inherit from the flask.views.MethodView class. Performance¶ Async functions require an event loop to run. Flask, as a WSGI application, uses one worker to handle one request/response cycle. When a request comes in to an async view, Flask will start an event loop in a thread, run the view function there, then return the result. Each request still ties up one worker, even for async views. The upside is that you can run async code within a view, for example to make multiple concurrent database queries, HTTP requests to an external API, etc. However, the number of requests your application can handle at one time will remain the same. Async is not inherently faster than sync code. Async is beneficial when performing concurrent IO-bound tasks, but will probably not improve CPU-bound tasks. Traditional Flask views will still be appropriate for most use cases, but Flask’s async support enables writing and using code that wasn’t possible natively before. Background tasks¶ Async functions will run in an event loop until they complete, at which stage the event loop will stop. This means any additional spawned tasks that haven’t completed when the async function completes will be cancelled. Therefore you cannot spawn background tasks, for example via asyncio.create_task. If you wish to use background tasks it is best to use a task queue to trigger background work, rather than spawn tasks in a view function. With that in mind you can spawn asyncio tasks by serving Flask with an ASGI server and utilising the asgiref WsgiToAsgi adapter as described in ASGI. This works as the adapter creates an event loop that runs continually. When to use Quart instead¶ Flask’s async support is less performant than async-first frameworks due to the way it is implemented. If you have a mainly async codebase it would make sense to consider Quart. Quart is a reimplementation of Flask based on the ASGI standard instead of WSGI. This allows it to handle many concurrent requests, long running requests, and websockets without requiring multiple worker processes or threads. It has also already been possible to run Flask with Gevent to get many of the benefits of async request handling. Gevent patches low-level Python functions to accomplish this, whereas async/await and ASGI use standard, modern Python capabilities. Deciding whether you should use gevent with Flask, or Quart, or something else is ultimately up to understanding the specific needs of your project. Extensions¶ Flask extensions predating Flask’s async support do not expect async views. If they provide decorators to add functionality to views, those will probably not work with async views because they will not await the function or be awaitable. Other functions they provide will not be awaitable either and will probably be blocking if called within an async view. Extension authors can support async functions by utilising the flask.Flask.ensure_sync() method. For example, if the extension provides a view function decorator add ensure_sync before calling the decorated function, def extension(func): @wraps(func) def wrapper(*args, **kwargs): ... # Extension logic return current_app.ensure_sync(func)(*args, **kwargs) return wrapper Check the changelog of the extension you want to use to see if they’ve implemented async support, or make a feature request or PR to them. Other event loops¶ At the moment Flask only supports asyncio. It’s possible to override flask.Flask.ensure_sync() to change how async functions are wrapped to use a different library. See Combining with async/await for an example. Contents Using async and await Performance Background tasks When to use Quart instead Extensions Other event loops Navigation Overview with Gevent Quick search\n\nExample:\n```text\n@app.route(\"/get-data\")\nasync def get_data():\n    data = await async_db_query(...)\n    return jsonify(data)\n```\n\nExample:\n```text\ndef extension(func):\n    @wraps(func)\n    def wrapper(*args, **kwargs):\n        ...  # Extension logic\n        return current_app.ensure_sync(func)(*args, **kwargs)\n\n    return wrapper\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.105Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":22,"estimatedTokens":1182}}70{"id":"doc-deferred_request_callbacks_flask_documentation_3-7f2ea67f","source":"documentation","title":"Deferred Request Callbacks — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/deferredcallbacks/","text":"Deferred Request Callbacks¶ One of the design principles of Flask is that response objects are created and passed down a chain of potential callbacks that can modify them or replace them. When the request handling starts, there is no response object yet. It is created as necessary either by a view function or by some other component in the system. What happens if you want to modify the response at a point where the response does not exist yet? A common example for that would be a before_request() callback that wants to set a cookie on the response object. One way is to avoid the situation. Very often that is possible. For instance you can try to move that logic into a after_request() callback instead. However, sometimes moving code there makes it more complicated or awkward to reason about. As an alternative, you can use after_this_request() to register callbacks that will execute after only the current request. This way you can defer code execution from anywhere in the application, based on the current request. At any time during a request, we can register a function to be called at the end of the request. For example you can remember the current language of the user in a cookie in a before_request() flask import request, after_this_request @app.before_request def detect_user_language(): language = request.cookies.get('user_lang') if language is = guess_language_from_request() # when the response exists, set a cookie with the language @after_this_request def remember_language(response): response.set_cookie('user_lang', language) return response g.language = language Navigation Overview Patterns for Flask Contents HTTP Method Overrides Quick search\n\nExample:\n```text\nfrom flask import request, after_this_request\n\n@app.before_request\ndef detect_user_language():\n    language = request.cookies.get('user_lang')\n\n    if language is None:\n        language = guess_language_from_request()\n\n        # when the response exists, set a cookie with the language\n        @after_this_request\n        def remember_language(response):\n            response.set_cookie('user_lang', language)\n            return response\n\n    g.language = language\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.105Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":1,"totalLines":23,"estimatedTokens":545}}71{"id":"doc-design_decisions_in_flask_flask_documentation_3_-d1caf843","source":"documentation","title":"Design Decisions in Flask — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/design/","text":"Design Decisions in Flask¶ If you are curious why Flask does certain things the way it does and not differently, this section is for you. This should give you an idea about some of the design decisions that may appear arbitrary and surprising at first, especially in direct comparison with other frameworks. The Explicit Application Object¶ A Python web application based on WSGI has to have one central callable object that implements the actual application. In Flask this is an instance of the Flask class. Each Flask application has to create an instance of this class itself and pass it the name of the module, but why can’t Flask do that itself? Without such an explicit application object the following flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'Hello World!' Would look like this hypothetical_flask import route @route('/') def index(): return 'Hello World!' There are three major reasons for this. The most important one is that implicit application objects require that there may only be one instance at the time. There are ways to fake multiple applications with a single application object, like maintaining a stack of applications, but this causes some problems I won’t outline here in detail. Now the question does a microframework need more than one application at the same time? A good example for this is unit testing. When you want to test something it can be very helpful to create a minimal application to test specific behavior. When the application object is deleted everything it allocated will be freed again. Another thing that becomes possible when you have an explicit object lying around in your code is that you can subclass the base class (Flask) to alter specific behavior. This would not be possible without hacks if the object were created ahead of time for you based on a class that is not exposed to you. But there is another very important reason why Flask depends on an explicit instantiation of that package name. Whenever you create a Flask instance you usually pass it __name__ as package name. Flask depends on that information to properly load resources relative to your module. With Python’s outstanding support for reflection it can then access the package to figure out where the templates and static files are stored (see open_resource()). Now obviously there are frameworks around that do not need any configuration and will still be able to load templates relative to your application module. But they have to use the current working directory for that, which is a very unreliable way to determine where the application is. The current working directory is process-wide and if you are running multiple applications in one process (which could happen in a webserver without you knowing) the paths will be off. webservers do not set the working directory to the directory of your application but to the document root which does not have to be the same folder. The third reason is “explicit is better than implicit”. That object is your WSGI application, you don’t have to remember anything else. If you want to apply a WSGI middleware, just wrap it and you’re done (though there are better ways to do that so that you do not lose the reference to the application object wsgi_app()). Furthermore this design makes it possible to use a factory function to create the application which is very helpful for unit testing and similar things (Application Factories). The Routing System¶ Flask uses the Werkzeug routing system which was designed to automatically order routes by complexity. This means that you can declare routes in arbitrary order and they will still work as expected. This is a requirement if you want to properly implement decorator based routing since decorators could be fired in undefined order when the application is split into multiple modules. Another design decision with the Werkzeug routing system is that routes in Werkzeug try to ensure that URLs are unique. Werkzeug will go quite far with that in that it will automatically redirect to a canonical URL if a route is ambiguous. One Template Engine¶ Flask decides on one template Why doesn’t Flask have a pluggable template engine interface? You can obviously use a different template engine, but Flask will still configure Jinja for you. While that limitation that Jinja is always configured will probably go away, the decision to bundle one template engine and use that will not. Template engines are like programming languages and each of those engines has a certain understanding about how things work. On the surface they all work the tell the engine to evaluate a template with a set of variables and take the return value as string. But that’s about where similarities end. Jinja for example has an extensive filter system, a certain way to do template inheritance, support for reusable blocks (macros) that can be used from inside templates and also from Python code, supports iterative template rendering, configurable syntax and more. On the other hand an engine like Genshi is based on XML stream evaluation, template inheritance by taking the availability of XPath into account and more. Mako on the other hand treats templates similar to Python modules. When it comes to connecting a template engine with an application or framework there is more than just rendering templates. For instance, Flask uses Jinja’s extensive autoescaping support. Also it provides ways to access macros from Jinja templates. A template abstraction layer that would not take the unique features of the template engines away is a science on its own and a too large undertaking for a microframework like Flask. Furthermore extensions can then easily depend on one template language being present. You can easily use your own templating language, but an extension could still depend on Jinja itself. What does “micro” mean?¶ “Micro” does not mean that your whole web application has to fit into a single Python file (although it certainly can), nor does it mean that Flask is lacking in functionality. The “micro” in microframework means Flask aims to keep the core simple but extensible. Flask won’t make many decisions for you, such as what database to use. Those decisions that it does make, such as what templating engine to use, are easy to change. Everything else is up to you, so that Flask can be everything you need and nothing you don’t. By default, Flask does not include a database abstraction layer, form validation or anything else where different libraries already exist that can handle that. Instead, Flask supports extensions to add such functionality to your application as if it was implemented in Flask itself. Numerous extensions provide database integration, form validation, upload handling, various open authentication technologies, and more. Flask may be “micro”, but it’s ready for production use on a variety of needs. Why does Flask call itself a microframework and yet it depends on two libraries (namely Werkzeug and Jinja). Why shouldn’t it? If we look over to the Ruby side of web development there we have a protocol very similar to WSGI. Just that it’s called Rack there, but besides that it looks very much like a WSGI rendition for Ruby. But nearly all applications in Ruby land do not work with Rack directly, but on top of a library with the same name. This Rack library has two equivalents in (formerly Paste) and Werkzeug. Paste is still around but from my understanding it’s sort of deprecated in favour of WebOb. The development of WebOb and Werkzeug started side by side with similar ideas in a good implementation of WSGI for other applications to take advantage. Flask is a framework that takes advantage of the work already done by Werkzeug to properly interface WSGI (which can be a complex task at times). Thanks to recent developments in the Python package infrastructure, packages with dependencies are no longer an issue and there are very few reasons against having libraries that depend on others. Thread Locals¶ Flask uses thread local objects (context local objects in fact, they support greenlet contexts as well) for request, session and an extra object you can put your own things on (g). Why is that and isn’t that a bad idea? 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. Async/await and ASGI support¶ Flask supports async coroutines for view functions by executing the coroutine on a separate thread instead of using an event loop on the main thread as an async-first (ASGI) framework would. This is necessary for Flask to remain backwards compatible with extensions and code built before async was introduced into Python. This compromise introduces a performance cost compared with the ASGI frameworks, due to the overhead of the threads. Due to how tied to WSGI Flask’s code is, it’s not clear if it’s possible to make the Flask class support ASGI and WSGI at the same time. Work is currently being done in Werkzeug to work with ASGI, which may eventually enable support in Flask as well. See Using async and await for more discussion. What Flask is, What Flask is Not¶ Flask will never have a database layer. It will not have a form library or anything else in that direction. Flask itself just bridges to Werkzeug to implement a proper WSGI application and to Jinja to handle templating. It also binds to a few common standard library packages such as logging. Everything else is up for extensions. Why is this the case? Because people have different preferences and requirements and Flask could not meet those if it would force any of this into the core. The majority of web applications will need a template engine in some sort. However not every application needs a SQL database. As your codebase grows, you are free to make the design decisions appropriate for your project. Flask will continue to provide a very simple glue layer to the best that Python has to offer. You can implement advanced patterns in SQLAlchemy or another database tool, introduce non-relational data persistence as appropriate, and take advantage of framework-agnostic tools built for WSGI, the Python web interface. The idea of Flask is to build a good foundation for all applications. Everything else is up to you or extensions. Contents Design Decisions in Flask The Explicit Application Object The Routing System One Template Engine What does “micro” mean? Thread Locals Async/await and ASGI support What Flask is, What Flask is Not Navigation Overview Extension Development Quick search\n\nExample:\n```text\nfrom flask import Flask\napp = Flask(__name__)\n\n@app.route('/')\ndef index():\n    return 'Hello World!'\n```\n\nExample:\n```text\nfrom hypothetical_flask import route\n\n@route('/')\ndef index():\n    return 'Hello World!'\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.106Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":22,"estimatedTokens":2758}}72{"id":"doc-background_tasks_with_celery_flask_documentation-a319e00a","source":"documentation","title":"Background Tasks with Celery — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/patterns/celery/","text":"Background Tasks with Celery¶ If your application has a long running task, such as processing some uploaded data or sending email, you don’t want to wait for it to finish during a request. Instead, use a task queue to send the necessary data to another process that will run the task in the background while the request returns immediately. Celery is a powerful task queue that can be used for simple background tasks as well as complex multi-stage programs and schedules. This guide will show you how to configure Celery using Flask. Read Celery’s First Steps with Celery guide to learn how to use Celery itself. The Flask repository contains an example based on the information on this page, which also shows how to use JavaScript to submit tasks and poll for progress and results. Install¶ Install Celery from PyPI, for example using pip: $ pip install celery Integrate Celery with Flask¶ You can use Celery without any integration with Flask, but it’s convenient to configure it through Flask’s config, and to let tasks access the Flask application. Celery uses similar ideas to Flask, with a Celery app object that has configuration and registers tasks. While creating a Flask app, use the following code to create and configure a Celery app as well. from celery import Celery, Task def celery_init_app(app: Flask) -> FlaskTask(Task): def __call__(self, *args: object, **kwargs: object) -> app.app_context(): return self.run(*args, **kwargs) celery_app = Celery(app.name, task_cls=FlaskTask) celery_app.config_from_object(app.config[\"CELERY\"]) celery_app.set_default() app.extensions[\"celery\"] = celery_app return celery_app This creates and returns a Celery app object. Celery configuration is taken from the CELERY key in the Flask configuration. The Celery app is set as the default, so that it is seen during each request. The Task subclass automatically runs task functions with a Flask app context active, so that services like your database connections are available. Here’s a basic example.py that configures Celery to use Redis for communication. We enable a result backend, but ignore results by default. This allows us to store results only for tasks where we care about the result. from flask import Flask app = Flask(__name__) app.config.from_mapping( CELERY=dict( broker_url=\"redis://localhost\", result_backend=\"redis://localhost\", task_ignore_result=True, ), ) celery_app = celery_init_app(app) Point the celery worker command at this and it will find the celery_app object. $ celery -A example worker --loglevel INFO You can also run the celery beat command to run tasks on a schedule. See Celery’s docs for more information about defining schedules. $ celery -A example beat --loglevel INFO Application Factory¶ When using the Flask application factory pattern, call the celery_init_app function inside the factory. It sets app.extensions[\"celery\"] to the Celery app object, which can be used to get the Celery app from the Flask app returned by the factory. def create_app() -> = Flask(__name__) app.config.from_mapping( CELERY=dict( broker_url=\"redis://localhost\", result_backend=\"redis://localhost\", task_ignore_result=True, ), ) app.config.from_prefixed_env() celery_init_app(app) return app To use celery commands, Celery needs an app object, but that’s no longer directly available. Create a make_celery.py file that calls the Flask app factory and gets the Celery app from the returned Flask app. from example import create_app flask_app = create_app() celery_app = flask_app.extensions[\"celery\"] Point the celery command to this file. $ celery -A make_celery worker --loglevel INFO $ celery -A make_celery beat --loglevel INFO Defining Tasks¶ Using @celery_app.task to decorate task functions requires access to the celery_app object, which won’t be available when using the factory pattern. It also means that the decorated tasks are tied to the specific Flask and Celery app instances, which could be an issue during testing if you change configuration for a test. Instead, use Celery’s @shared_task decorator. This creates task objects that will access whatever the “current app” is, which is a similar concept to Flask’s blueprints and app context. This is why we called celery_app.set_default() above. Here’s an example task that adds two numbers together and returns the result. from celery import shared_task @shared_task(ignore_result=False) def add_together(a: int, ) -> a + b Earlier, we configured Celery to ignore task results by default. Since we want to know the return value of this task, we set ignore_result=False. On the other hand, a task that didn’t need a result, such as sending an email, wouldn’t set this. Calling Tasks¶ The decorated function becomes a task object with methods to call it in the background. The simplest way is to use the delay(*args, **kwargs) method. See Celery’s docs for more methods. A Celery worker must be running to run the task. Starting a worker is shown in the previous sections. from flask import request @app.post(\"/add\") def start_add() -> dict[str, object]: a = request.form.get(\"a\", type=int) b = request.form.get(\"b\", type=int) result = add_together.delay(a, b) return {\"result_id\": result.id} The route doesn’t get the task’s result immediately. That would defeat the purpose by blocking the response. Instead, we return the running task’s result id, which we can use later to get the result. Getting Results¶ To fetch the result of the task we started above, we’ll add another route that takes the result id we returned before. We return whether the task is finished (ready), whether it finished successfully, and what the return value (or error) was if it is finished. from celery.result import AsyncResult @app.get(\"/result/<id>\") def task_result(id: str) -> dict[str, object]: result = AsyncResult(id) return { \"ready\": result.ready(), \"successful\": result.successful(), \"value\": result.result if result.ready() else None, } Now you can start the task using the first route, then poll for the result using the second route. This keeps the Flask request workers from being blocked waiting for tasks to finish. The Flask repository contains an example using JavaScript to submit tasks and poll for progress and results. Passing Data to Tasks¶ The “add” task above took two integers as arguments. To pass arguments to tasks, Celery has to serialize them to a format that it can pass to other processes. Therefore, passing complex objects is not recommended. For example, it would be impossible to pass a SQLAlchemy model object, since that object is probably not serializable and is tied to the session that queried it. Pass the minimal amount of data necessary to fetch or recreate any complex data within the task. Consider a task that will run when the logged in user asks for an archive of their data. The Flask request knows the logged in user, and has the user object queried from the database. It got that by querying the database for a given id, so the task can do the same thing. Pass the user’s id rather than the user object. @shared_task def generate_user_archive(user_id: str) -> = db.session.get(User, user_id) ... generate_user_archive.delay(current_user.id) Contents Background Tasks with Celery Install Integrate Celery with Flask Application Factory Defining Tasks Calling Tasks Getting Results Passing Data to Tasks Navigation Overview Patterns for Flask Content Checksums Flask Quick search\n\nExample:\n```text\n$ pip install celery\n```\n\nExample:\n```text\nfrom celery import Celery, Task\n\ndef celery_init_app(app: Flask) -> Celery:\n    class FlaskTask(Task):\n        def __call__(self, *args: object, **kwargs: object) -> object:\n            with app.app_context():\n                return self.run(*args, **kwargs)\n\n    celery_app = Celery(app.name, task_cls=FlaskTask)\n    celery_app.config_from_object(app.config[\"CELERY\"])\n    celery_app.set_default()\n    app.extensions[\"celery\"] = celery_app\n    return celery_app\n```\n\nExample:\n```text\nfrom flask import Flask\n\napp = Flask(__name__)\napp.config.from_mapping(\n    CELERY=dict(\n        broker_url=\"redis://localhost\",\n        result_backend=\"redis://localhost\",\n        task_ignore_result=True,\n    ),\n)\ncelery_app = celery_init_app(app)\n```\n\nExample:\n```text\n$ celery -A example worker --loglevel INFO\n```\n\nExample:\n```text\n$ celery -A example beat --loglevel INFO\n```\n\nExample:\n```text\ndef create_app() -> Flask:\n    app = Flask(__name__)\n    app.config.from_mapping(\n        CELERY=dict(\n            broker_url=\"redis://localhost\",\n            result_backend=\"redis://localhost\",\n            task_ignore_result=True,\n        ),\n    )\n    app.config.from_prefixed_env()\n    celery_init_app(app)\n    return app\n```\n\nExample:\n```text\nfrom example import create_app\n\nflask_app = create_app()\ncelery_app = flask_app.extensions[\"celery\"]\n```\n\nExample:\n```text\n$ celery -A make_celery worker --loglevel INFO\n$ celery -A make_celery beat --loglevel INFO\n```\n\nExample:\n```text\nfrom celery import shared_task\n\n@shared_task(ignore_result=False)\ndef add_together(a: int, b: int) -> int:\n    return a + b\n```\n\nExample:\n```text\nfrom flask import request\n\n@app.post(\"/add\")\ndef start_add() -> dict[str, object]:\n    a = request.form.get(\"a\", type=int)\n    b = request.form.get(\"b\", type=int)\n    result = add_together.delay(a, b)\n    return {\"result_id\": result.id}\n```\n\nExample:\n```text\nfrom celery.result import AsyncResult\n\n@app.get(\"/result/<id>\")\ndef task_result(id: str) -> dict[str, object]:\n    result = AsyncResult(id)\n    return {\n        \"ready\": result.ready(),\n        \"successful\": result.successful(),\n        \"value\": result.result if result.ready() else None,\n    }\n```\n\nExample:\n```text\n@shared_task\ndef generate_user_archive(user_id: str) -> None:\n    user = db.session.get(User, user_id)\n    ...\n\ngenerate_user_archive.delay(current_user.id)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.107Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":12,"totalLines":125,"estimatedTokens":2457}}73{"id":"doc-api_flask_documentation_3_1_x-24ec5c2a","source":"documentation","title":"API — Flask Documentation (3.1.x)","url":"https://flask.palletsprojects.com/en/stable/api/","text":"API¶ This part of the documentation covers all the interfaces of Flask. For parts where Flask depends on external libraries, we document the most important right here and provide links to the canonical documentation. Application Object¶ class flask.Flask(import_name, static_url_path=None, static_folder='static', static_host=None, host_matching=False, subdomain_matching=False, template_folder='templates', instance_path=None, instance_relative_config=False, root_path=None)¶ The flask object implements a WSGI application and acts as the central object. It is passed the name of the module or package of the application. Once it is created it will act as a central registry for the view functions, the URL rules, template configuration and much more. The name of the package is used to resolve resources from inside the package or the folder the module is contained in depending on if the package parameter resolves to an actual python package (a folder with an __init__.py file inside) or a standard module (just a ¶ Options that are passed to the Jinja environment in create_jinja_environment(). Changing these options after the environment is created (accessing jinja_env) will have no effect. Changelog Changed in version 1.1.0: This is a dict instead of an ImmutableDict to allow easier configuration. json_provider_class¶ alias of DefaultJSONProvider property ¶ A standard Python Logger for the app, with the same name as name. In debug mode, the logger’s level will be set to DEBUG. If there are no handlers configured, a default handler will be added. See Logging for more information. Changelog Changed in version 1.1.0: The logger takes the same name as name rather than hard-coding \"flask.app\". Changed in version 1.0.0: Behavior was simplified. The logger is always named \"flask.app\". The level is only set during configuration, it doesn’t check app.debug each time. Only one format is used, not different ones depending on app.debug. No handlers are removed, and a handler is only added if no handlers are already configured. Added in version 0.3. make_aborter()¶ Create the object to assign to aborter. That object is called by flask.abort() to raise HTTP errors, and can be called directly as well. By default, this creates an instance of aborter_class, which defaults to werkzeug.exceptions.Aborter. Changelog Added in version 2.2. Return make_config(instance_relative=False)¶ Used to create the config attribute by the Flask constructor. The instance_relative parameter is passed in from the constructor of Flask (there named instance_relative_config) and indicates if the config should be relative to the instance path or the root path of the application. Changelog Added in version 0.8. (bool) Return property ¶ The name of the application. This is usually the import name with the difference that it’s guessed from the run file if the import name is main. This name is used as a display name when Flask needs the name of the application. It can be set and overridden to change the value. Changelog Added in version 0.8. patch(rule, **options)¶ Shortcut for route() with methods=[\"PATCH\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] permanent_session_lifetime¶ A timedelta which is used to set the expiration date of a permanent session. The default is 31 days which makes a permanent session survive for roughly one month. This attribute can also be configured from the config with the PERMANENT_SESSION_LIFETIME configuration key. Defaults to timedelta(days=31) post(rule, **options)¶ Shortcut for route() with methods=[\"POST\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] put(rule, **options)¶ Shortcut for route() with methods=[\"PUT\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] redirect(location, code=302)¶ Create a redirect response object. This is called by flask.redirect(), and can be called directly as well. (str) – The URL to redirect to. code (int) – The status code for the redirect. Return Changelog Added in version 2.2: Moved from flask.redirect, which calls this method. register_blueprint(blueprint, **options)¶ Register a Blueprint on the application. Keyword arguments passed to this method will override the defaults set on the blueprint. Calls the blueprint’s register() method after recording the blueprint in the application’s blueprints. (Blueprint) – The blueprint to register. url_prefix – Blueprint routes will be prefixed with this. subdomain – Blueprint routes will match on this subdomain. url_defaults – Blueprint routes will use these default values for view arguments. options (t.Any) – Additional keyword arguments are passed to BlueprintSetupState. They can be accessed in record() callbacks. Return Changelog Changed in version 2.0.1: The name option can be used to change the (pre-dotted) name the blueprint is registered with. This allows the same blueprint to be registered multiple times with unique names for url_for. Added in version 0.7. register_error_handler(code_or_exception, f)¶ Alternative error attach function to the errorhandler() decorator that is more straightforward to use for non decorator usage. Changelog Added in version 0.7. (type[Exception] | int) f (ft.ErrorHandlerCallable) Return route(rule, **options)¶ Decorate a view function to register it with the given URL rule and options. Calls add_url_rule(), which has more details about the implementation. @app.route(\"/\") def index(): return \"Hello, World!\" See URL Route Registrations. The endpoint name for the route defaults to the name of the view function if the endpoint parameter isn’t passed. The methods parameter defaults to [\"GET\"]. HEAD and OPTIONS are added automatically. (str) – The URL rule string. options (Any) – Extra options passed to the Rule object. Return [[T_route], T_route] secret_key¶ If a secret key is set, cryptographic components can use this to sign cookies and other things. Set this to a complex random value when you want to use the secure cookie for instance. This attribute can also be configured from the config with the SECRET_KEY configuration key. Defaults to None. select_jinja_autoescape(filename)¶ Returns True if autoescaping should be active for the given template name. If no template name is given, returns True. Changelog Changed in version 2.2: Autoescaping is now enabled by default for .svg files. Added in version 0.5. (str | None) Return shell_context_processor(f)¶ Registers a shell context processor function. Changelog Added in version 0.11. (T_shell_context_processor) Return should_ignore_error(error)¶ This is called to figure out if an error should be ignored or not as far as the teardown system is concerned. If this function returns True then the teardown handlers will not be passed the error. Changelog Added in version 0.10. (BaseException | None) Return property | None¶ The absolute path to the configured static folder. None if no static folder is set. property | None¶ The URL prefix that the static route will be accessible from. If it was not configured during init, it is derived from static_folder. teardown_appcontext(f)¶ Registers a function to be called when the application context is popped. The application context is typically popped after the request context for each request, at the end of CLI commands, or after a manually pushed context ends. with app.app_context(): ... When the with block exits (or ctx.pop() is called), the teardown functions are called just before the app context is made inactive. Since a request context typically also manages an application context it would also be called when you pop a request context. When a teardown function was called because of an unhandled exception it will be passed an error object. If an errorhandler() is registered, it will handle the exception and the teardown will not receive it. Teardown functions must avoid raising exceptions. If they execute code that might fail they must surround that code with a try/except block and log any errors. The return values of teardown functions are ignored. Changelog Added in version 0.9. (T_teardown) Return teardown_request(f)¶ Register a function to be called when the request context is popped. Typically this happens at the end of each request, but contexts may be pushed manually as well during testing. with app.test_request_context(): ... When the with block exits (or ctx.pop() is called), the teardown functions are called just before the request context is made inactive. When a teardown function was called because of an unhandled exception it will be passed an error object. If an errorhandler() is registered, it will handle the exception and the teardown will not receive it. Teardown functions must avoid raising exceptions. If they execute code that might fail they must surround that code with a try/except block and log any errors. The return values of teardown functions are ignored. This is available on both app and blueprint objects. When used on an app, this executes after every request. When used on a blueprint, this executes after every request that the blueprint handles. To register with a blueprint and execute after every request, use Blueprint.teardown_app_request(). (T_teardown) Return template_filter(name=None)¶ A decorator that is used to register custom template filter. You can specify a name for the filter, otherwise the function name will be used. Example: @app.template_filter() def reverse(s): return s[::-1] (str | None) – the optional name of the filter, otherwise the function name will be used. Return [[T_template_filter], T_template_filter] template_global(name=None)¶ A decorator that is used to register a custom template global function. You can specify a name for the global function, otherwise the function name will be used. Example: @app.template_global() def double(n): return 2 * n Changelog Added in version 0.10. (str | None) – the optional name of the global function, otherwise the function name will be used. Return [[T_template_global], T_template_global] template_test(name=None)¶ A decorator that is used to register custom template test. You can specify a name for the test, otherwise the function name will be used. Example: @app.template_test() def is_prime(n): if n == True for i in range(2, int(math.ceil(math.sqrt(n))) + 1): if n % i == False return True Changelog Added in version 0.10. (str | None) – the optional name of the test, otherwise the function name will be used. Return [[T_template_test], T_template_test] [FlaskCliRunner] | None = None¶ The CliRunner subclass, by default FlaskCliRunner that is used by test_cli_runner(). Its __init__ method should take a Flask app object as the first argument. Changelog Added in version 1.0. [FlaskClient] | None = None¶ The test_client() method creates an instance of this test client class. Defaults to FlaskClient. Changelog Added in version 0.7. testing¶ The testing flag. Set this to True to enable the test mode of Flask extensions (and in the future probably also Flask itself). For example this might activate test helpers that have an additional runtime cost which should not be enabled by default. If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the default it’s implicitly enabled. This attribute can also be configured from the config with the TESTING configuration key. Defaults to False. trap_http_exception(e)¶ Checks if an HTTP exception should be trapped or not. By default this will return False for all exceptions except for a bad request key error if TRAP_BAD_REQUEST_ERRORS is set to True. It also returns True if TRAP_HTTP_EXCEPTIONS is set to True. This is called for all HTTP exceptions raised by a view function. If it returns True for any exception the error handler for this exception is not called and it shows up as regular exception in the traceback. This is helpful for debugging implicitly raised HTTP exceptions. Changelog Changed in version 1.0: Bad request errors are not trapped by default in debug mode. Added in version 0.8. (Exception) Return url_defaults(f)¶ Callback function for URL defaults for all view functions of the application. It’s called with the endpoint and values and should update the values passed in place. This is available on both app and blueprint objects. When used on an app, this is called for every request. When used on a blueprint, this is called for requests that the blueprint handles. To register with a blueprint and affect every request, use Blueprint.app_url_defaults(). (T_url_defaults) Return url_map_class¶ alias of Map url_rule_class¶ alias of Rule url_value_preprocessor(f)¶ Register a URL value preprocessor function for all view functions in the application. These functions will be called before the before_request() functions. The function can modify the values captured from the matched url before they are passed to the view. For example, this can be used to pop a common language code value and place it in g rather than pass it to every view. The function is passed the endpoint name and values dict. The return value is ignored. This is available on both app and blueprint objects. When used on an app, this is called for every request. When used on a blueprint, this is called for requests that the blueprint handles. To register with a blueprint and affect every request, use Blueprint.app_url_value_preprocessor(). (T_url_value_preprocessor) Return instance_path¶ Holds the path to the instance folder. Changelog Added in version 0.8. config¶ The configuration dictionary as Config. This behaves exactly like a regular dictionary but supports additional methods to load a config from files. aborter¶ An instance of aborter_class created by make_aborter(). This is called by flask.abort() to raise HTTP errors, and can be called directly as well. Changelog Added in version 2.2: Moved from flask.abort, which calls this object. ¶ Provides access to JSON methods. Functions in flask.json will call methods on this provider when the application context is active. Used for handling JSON requests and responses. An instance of json_provider_class. Can be customized by changing that attribute on a subclass, or by assigning to this attribute afterwards. The default, DefaultJSONProvider, uses Python’s built-in json library. A different provider can use a different JSON library. Changelog Added in version 2.2. [t.Callable[[Exception, str, dict[str, t.Any]], str]]¶ A list of functions that are called by handle_url_build_error() when url_for() raises a BuildError. Each function is called with error, endpoint and values. If a function returns None or raises a BuildError, it is skipped. Otherwise, its return value is returned by url_for. Changelog Added in version 0.9. [ft.TeardownCallable]¶ A list of functions that are called when the application context is destroyed. Since the application context is also torn down if the request ends this is the place to store code that disconnects from databases. Changelog Added in version 0.9. [ft.ShellContextProcessorCallable]¶ A list of shell context processor functions that should be run when a shell context is created. Changelog Added in version 0.11. [str, Blueprint]¶ Maps registered blueprint names to blueprint objects. The dict retains the order the blueprints were registered in. Blueprints can be registered multiple times, this dict does not track how often they were attached. Changelog Added in version 0.7. [str, t.Any]¶ a place where extensions can store application specific state. For example this is where an extension could store database engines and similar things. The key must match the name of the extension module. For example in case of a “Flask-Foo” extension in flask_foo, the key would be 'foo'. Changelog Added in version 0.7. url_map¶ The Map for this instance. You can use this to change the routing converters after the class was created but before any routes are connected. werkzeug.routing import BaseConverter class ListConverter(BaseConverter): def to_python(self, value): return value.split(',') def to_url(self, values): return ','.join(super(ListConverter, self).to_url(value) for value in values) app = Flask(__name__) app.url_map.converters['list'] = ListConverter import_name¶ The name of the package or module that this object belongs to. Do not change this once it is set by the constructor. template_folder¶ The path to the templates folder, relative to root_path, to add to the template loader. None if templates should not be added. root_path¶ Absolute path to the package on the filesystem. Used to look up resources contained in the package. [str, ft.RouteCallable]¶ A dictionary mapping endpoint names to view functions. To register a view function, use the route() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]]]¶ A data structure of registered error handlers, in the format {scope: {code: {class: handler}}}. The scope key is the name of a blueprint the handlers are active for, or None for all requests. The code key is the HTTP status code for HTTPException, or None for other exceptions. The innermost dictionary maps exception classes to handler functions. To register an error handler, use the errorhandler() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable]]¶ A data structure of functions to call at the beginning of each request, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the before_request() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]]]¶ A data structure of functions to call at the end of each request, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the after_request() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.TeardownCallable]]¶ A data structure of functions to call at the end of each request even if an exception is raised, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the teardown_request() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable]]¶ A data structure of functions to call to pass extra context values when rendering templates, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the context_processor() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.URLValuePreprocessorCallable]]¶ A data structure of functions to call to modify the keyword arguments passed to the view function, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the url_value_preprocessor() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.URLDefaultCallable]]¶ A data structure of functions to call to modify the keyword arguments when generating URLs, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the url_defaults() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. Blueprint Objects¶ class flask.Blueprint(name, import_name, static_folder=None, static_url_path=None, template_folder=None, url_prefix=None, subdomain=None, url_defaults=None, root_path=None, cli_group=_sentinel)¶ (str) import_name (str) static_folder (str | os.PathLike[str] | None) static_url_path (str | None) template_folder (str | os.PathLike[str] | None) url_prefix (str | None) subdomain (str | None) url_defaults (dict[str, t.Any] | None) root_path (str | None) cli_group (str | None) ¶ The Click command group for registering CLI commands for this object. The commands are available from the flask command once the application has been discovered and blueprints have been registered. get_send_file_max_age(filename)¶ Used by send_file() to determine the max_age cache value for a given file path if it wasn’t passed. By default, this returns SEND_FILE_MAX_AGE_DEFAULT from the configuration of current_app. This defaults to None, which tells the browser to use conditional requests instead of a timed cache, which is usually preferable. Note this is a duplicate of the same method in the Flask class. Changelog Changed in version 2.0: The default configuration is None instead of 12 hours. Added in version 0.9. (str | None) Return | None send_static_file(filename)¶ The view function used to serve files from static_folder. A route is automatically registered for this view at static_url_path if static_folder is set. Note this is a duplicate of the same method in the Flask class. Changelog Added in version 0.5. (str) Return open_resource(resource, mode='rb', encoding='utf-8')¶ Open a resource file relative to root_path for reading. The blueprint-relative equivalent of the app’s open_resource() method. (str) – Path to the resource relative to root_path. mode (str) – Open the file in this mode. Only reading is supported, valid values are \"r\" (or \"rt\") and \"rb\". encoding (str | None) – Open the file with this encoding when opening in text mode. This is ignored when opening in binary mode. Return Changed in version 3.1: Added the encoding parameter. add_app_template_filter(f, name=None)¶ Register a template filter, available in any template rendered by the application. Works like the app_template_filter() decorator. Equivalent to Flask.add_template_filter(). (str | None) – the optional name of the filter, otherwise the function name will be used. f (Callable[[...], Any]) Return add_app_template_global(f, name=None)¶ Register a template global, available in any template rendered by the application. Works like the app_template_global() decorator. Equivalent to Flask.add_template_global(). Changelog Added in version 0.10. (str | None) – the optional name of the global, otherwise the function name will be used. f (Callable[[...], Any]) Return add_app_template_test(f, name=None)¶ Register a template test, available in any template rendered by the application. Works like the app_template_test() decorator. Equivalent to Flask.add_template_test(). Changelog Added in version 0.10. (str | None) – the optional name of the test, otherwise the function name will be used. f (Callable[[...], bool]) Return add_url_rule(rule, endpoint=None, view_func=None, provide_automatic_options=None, **options)¶ Register a URL rule with the blueprint. See Flask.add_url_rule() for full documentation. The URL rule is prefixed with the blueprint’s URL prefix. The endpoint name, used with url_for(), is prefixed with the blueprint’s name. (str) endpoint (str | None) view_func (ft.RouteCallable | None) provide_automatic_options (bool | None) options (t.Any) Return after_app_request(f)¶ Like after_request(), but after every request, not only those handled by the blueprint. Equivalent to Flask.after_request(). (T_after_request) Return after_request(f)¶ Register a function to run after each request to this object. The function is called with the response object, and must return a response object. This allows the functions to modify or replace the response before it is sent. If a function raises an exception, any remaining after_request functions will not be called. Therefore, this should not be used for actions that must execute, such as to close resources. Use teardown_request() for that. This is available on both app and blueprint objects. When used on an app, this executes after every request. When used on a blueprint, this executes after every request that the blueprint handles. To register with a blueprint and execute after every request, use Blueprint.after_app_request(). (T_after_request) Return app_context_processor(f)¶ Like context_processor(), but for templates rendered by every view, not only by the blueprint. Equivalent to Flask.context_processor(). (T_template_context_processor) Return app_errorhandler(code)¶ Like errorhandler(), but for every request, not only those handled by the blueprint. Equivalent to Flask.errorhandler(). (type[Exception] | int) Return [[T_error_handler], T_error_handler] app_template_filter(name=None)¶ Register a template filter, available in any template rendered by the application. Equivalent to Flask.template_filter(). (str | None) – the optional name of the filter, otherwise the function name will be used. Return [[T_template_filter], T_template_filter] app_template_global(name=None)¶ Register a template global, available in any template rendered by the application. Equivalent to Flask.template_global(). Changelog Added in version 0.10. (str | None) – the optional name of the global, otherwise the function name will be used. Return [[T_template_global], T_template_global] app_template_test(name=None)¶ Register a template test, available in any template rendered by the application. Equivalent to Flask.template_test(). Changelog Added in version 0.10. (str | None) – the optional name of the test, otherwise the function name will be used. Return [[T_template_test], T_template_test] app_url_defaults(f)¶ Like url_defaults(), but for every request, not only those handled by the blueprint. Equivalent to Flask.url_defaults(). (T_url_defaults) Return app_url_value_preprocessor(f)¶ Like url_value_preprocessor(), but for every request, not only those handled by the blueprint. Equivalent to Flask.url_value_preprocessor(). (T_url_value_preprocessor) Return before_app_request(f)¶ Like before_request(), but before every request, not only those handled by the blueprint. Equivalent to Flask.before_request(). (T_before_request) Return before_request(f)¶ Register a function to run before each request. For example, this can be used to open a database connection, or to load the logged in user from the session. @app.before_request def load_user(): if \"user_id\" in = db.session.get(session[\"user_id\"]) The function will be called without any arguments. If it returns a non-None value, the value is handled as if it was the return value from the view, and further request handling is stopped. This is available on both app and blueprint objects. When used on an app, this executes before every request. When used on a blueprint, this executes before every request that the blueprint handles. To register with a blueprint and execute before every request, use Blueprint.before_app_request(). (T_before_request) Return context_processor(f)¶ Registers a template context processor function. These functions run before rendering a template. The keys of the returned dict are added as variables available in the template. This is available on both app and blueprint objects. When used on an app, this is called for every rendered template. When used on a blueprint, this is called for templates rendered from the blueprint’s views. To register with a blueprint and affect every template, use Blueprint.app_context_processor(). (T_template_context_processor) Return delete(rule, **options)¶ Shortcut for route() with methods=[\"DELETE\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] endpoint(endpoint)¶ Decorate a view function to register it for the given endpoint. Used if a rule is added without a view_func with add_url_rule(). app.add_url_rule(\"/ex\", endpoint=\"example\") @app.endpoint(\"example\") def example(): ... (str) – The endpoint name to associate with the view function. Return [[F], F] errorhandler(code_or_exception)¶ Register a function to handle errors by code or exception class. A decorator that is used to register a function given an error code. Example: @app.errorhandler(404) def page_not_found(error): return 'This page does not exist', 404 You can also register handlers for arbitrary exceptions: @app.errorhandler(DatabaseError) def special_exception_handler(error): return 'Database connection failed', 500 This is available on both app and blueprint objects. When used on an app, this can handle errors from every request. When used on a blueprint, this can handle errors from requests that the blueprint handles. To register with a blueprint and affect every request, use Blueprint.app_errorhandler(). Changelog Added in version 0.7: Use register_error_handler() instead of modifying error_handler_spec directly, for application wide error handlers. Added in version 0.7: One can now additionally also register custom exception types that do not necessarily have to be a subclass of the HTTPException class. (type[Exception] | int) – the code as integer for the handler, or an arbitrary exception Return [[T_error_handler], T_error_handler] get(rule, **options)¶ Shortcut for route() with methods=[\"GET\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] property ¶ True if static_folder is set. Changelog Added in version 0.5. property | None¶ The Jinja loader for this object’s templates. By default this is a class jinja2.loaders.FileSystemLoader to template_folder if it is set. Changelog Added in version 0.5. make_setup_state(app, options, first_registration=False)¶ Creates an instance of BlueprintSetupState() object that is later passed to the register callback functions. Subclasses can override this to return a subclass of the setup state. (App) options (dict[str, t.Any]) first_registration (bool) Return patch(rule, **options)¶ Shortcut for route() with methods=[\"PATCH\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] post(rule, **options)¶ Shortcut for route() with methods=[\"POST\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] put(rule, **options)¶ Shortcut for route() with methods=[\"PUT\"]. Changelog Added in version 2.0. (str) options (Any) Return [[T_route], T_route] record(func)¶ Registers a function that is called when the blueprint is registered on the application. This function is called with the state as argument as returned by the make_setup_state() method. (Callable[[BlueprintSetupState], None]) Return record_once(func)¶ Works like record() but wraps the function in another function that will ensure the function is only called once. If the blueprint is registered a second time on the application, the function passed is not called. (Callable[[BlueprintSetupState], None]) Return register(app, options)¶ Called by Flask.register_blueprint() to register all views and callbacks registered on the blueprint with the application. Creates a BlueprintSetupState and calls each record() callback with it. (App) – The application this blueprint is being registered with. options (dict[str, t.Any]) – Keyword arguments forwarded from register_blueprint(). Return Changelog Changed in version 2.3: Nested blueprints now correctly apply subdomains. Changed in version 2.1: Registering the same blueprint with the same name multiple times is an error. Changed in version 2.0.1: Nested blueprints are registered with their dotted name. This allows different blueprints with the same name to be nested at different locations. Changed in version 2.0.1: The name option can be used to change the (pre-dotted) name the blueprint is registered with. This allows the same blueprint to be registered multiple times with unique names for url_for. register_blueprint(blueprint, **options)¶ Register a Blueprint on this blueprint. Keyword arguments passed to this method will override the defaults set on the blueprint. Changelog Changed in version 2.0.1: The name option can be used to change the (pre-dotted) name the blueprint is registered with. This allows the same blueprint to be registered multiple times with unique names for url_for. Added in version 2.0. (Blueprint) options (Any) Return register_error_handler(code_or_exception, f)¶ Alternative error attach function to the errorhandler() decorator that is more straightforward to use for non decorator usage. Changelog Added in version 0.7. (type[Exception] | int) f (ft.ErrorHandlerCallable) Return route(rule, **options)¶ Decorate a view function to register it with the given URL rule and options. Calls add_url_rule(), which has more details about the implementation. @app.route(\"/\") def index(): return \"Hello, World!\" See URL Route Registrations. The endpoint name for the route defaults to the name of the view function if the endpoint parameter isn’t passed. The methods parameter defaults to [\"GET\"]. HEAD and OPTIONS are added automatically. (str) – The URL rule string. options (Any) – Extra options passed to the Rule object. Return [[T_route], T_route] property | None¶ The absolute path to the configured static folder. None if no static folder is set. property | None¶ The URL prefix that the static route will be accessible from. If it was not configured during init, it is derived from static_folder. teardown_app_request(f)¶ Like teardown_request(), but after every request, not only those handled by the blueprint. Equivalent to Flask.teardown_request(). (T_teardown) Return teardown_request(f)¶ Register a function to be called when the request context is popped. Typically this happens at the end of each request, but contexts may be pushed manually as well during testing. with app.test_request_context(): ... When the with block exits (or ctx.pop() is called), the teardown functions are called just before the request context is made inactive. When a teardown function was called because of an unhandled exception it will be passed an error object. If an errorhandler() is registered, it will handle the exception and the teardown will not receive it. Teardown functions must avoid raising exceptions. If they execute code that might fail they must surround that code with a try/except block and log any errors. The return values of teardown functions are ignored. This is available on both app and blueprint objects. When used on an app, this executes after every request. When used on a blueprint, this executes after every request that the blueprint handles. To register with a blueprint and execute after every request, use Blueprint.teardown_app_request(). (T_teardown) Return url_defaults(f)¶ Callback function for URL defaults for all view functions of the application. It’s called with the endpoint and values and should update the values passed in place. This is available on both app and blueprint objects. When used on an app, this is called for every request. When used on a blueprint, this is called for requests that the blueprint handles. To register with a blueprint and affect every request, use Blueprint.app_url_defaults(). (T_url_defaults) Return url_value_preprocessor(f)¶ Register a URL value preprocessor function for all view functions in the application. These functions will be called before the before_request() functions. The function can modify the values captured from the matched url before they are passed to the view. For example, this can be used to pop a common language code value and place it in g rather than pass it to every view. The function is passed the endpoint name and values dict. The return value is ignored. This is available on both app and blueprint objects. When used on an app, this is called for every request. When used on a blueprint, this is called for requests that the blueprint handles. To register with a blueprint and affect every request, use Blueprint.app_url_value_preprocessor(). (T_url_value_preprocessor) Return import_name¶ The name of the package or module that this object belongs to. Do not change this once it is set by the constructor. template_folder¶ The path to the templates folder, relative to root_path, to add to the template loader. None if templates should not be added. root_path¶ Absolute path to the package on the filesystem. Used to look up resources contained in the package. [str, ft.RouteCallable]¶ A dictionary mapping endpoint names to view functions. To register a view function, use the route() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]]]¶ A data structure of registered error handlers, in the format {scope: {code: {class: handler}}}. The scope key is the name of a blueprint the handlers are active for, or None for all requests. The code key is the HTTP status code for HTTPException, or None for other exceptions. The innermost dictionary maps exception classes to handler functions. To register an error handler, use the errorhandler() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable]]¶ A data structure of functions to call at the beginning of each request, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the before_request() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]]]¶ A data structure of functions to call at the end of each request, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the after_request() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.TeardownCallable]]¶ A data structure of functions to call at the end of each request even if an exception is raised, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the teardown_request() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable]]¶ A data structure of functions to call to pass extra context values when rendering templates, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the context_processor() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.URLValuePreprocessorCallable]]¶ A data structure of functions to call to modify the keyword arguments passed to the view function, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the url_value_preprocessor() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. [ft.AppOrBlueprintKey, list[ft.URLDefaultCallable]]¶ A data structure of functions to call to modify the keyword arguments when generating URLs, in the format {scope: [functions]}. The scope key is the name of a blueprint the functions are active for, or None for all requests. To register a function, use the url_defaults() decorator. This data structure is internal. It should not be modified directly and its format may change at any time. Incoming Request Data¶ class flask.Request(environ, populate_request=True, shallow=False)¶ The request object used by default in Flask. Remembers the matched endpoint and view arguments. It is what ends up as request. If you want to replace the request object used you can subclass this and set request_class to your subclass. The request object is a Request subclass and provides all of the attributes Werkzeug defines plus a few Flask specific ones. (WSGIEnvironment) populate_request (bool) shallow (bool) | None = None¶ The internal URL rule that matched the request. This can be useful to inspect which methods are allowed for the URL from a before/after handler (request.url_rule.methods) etc. Though if the request’s method was invalid for the URL rule, the valid list is available in routing_exception.valid_methods instead (an attribute of the Werkzeug exception MethodNotAllowed) because the request was never internally bound. Changelog Added in version 0.6. [str, t.Any] | None = None¶ A dict of view arguments that matched the request. If an exception happened when matching, this will be None. | None = None¶ If matching the URL failed, this is the exception that will be raised / was raised as part of the request handling. This is usually a NotFound exception or something similar. property | None¶ The maximum number of bytes that will be read during this request. If this limit is exceeded, a 413 RequestEntityTooLarge error is raised. If it is set to None, no limit is enforced at the Flask application level. However, if it is None and the request has no Content-Length header and the WSGI server does not indicate that it terminates the stream, then no data is read to avoid an infinite stream. Each request defaults to the MAX_CONTENT_LENGTH config, which defaults to None. It can be set on a specific request to apply the limit to that specific view. This should be set appropriately based on an application’s or view’s specific needs. Changed in version 3.1: This can be set per-request. Changelog Changed in version 0.6: This is configurable through Flask config. property | None¶ The maximum size in bytes any non-file form field may be in a multipart/form-data body. If this limit is exceeded, a 413 RequestEntityTooLarge error is raised. If it is set to None, no limit is enforced at the Flask application level. Each request defaults to the MAX_FORM_MEMORY_SIZE config, which defaults to 500_000. It can be set on a specific request to apply the limit to that specific view. This should be set appropriately based on an application’s or view’s specific needs. Changed in version 3.1: This is configurable through Flask config. property | None¶ The maximum number of fields that may be present in a multipart/form-data body. If this limit is exceeded, a 413 RequestEntityTooLarge error is raised. If it is set to None, no limit is enforced at the Flask application level. Each request defaults to the MAX_FORM_PARTS config, which defaults to 1_000. It can be set on a specific request to apply the limit to that specific view. This should be set appropriately based on an application’s or view’s specific needs. Changed in version 3.1: This is configurable through Flask config. property | None¶ The endpoint that matched the request URL. This will be None if matching failed or has not been performed yet. This in combination with view_args can be used to reconstruct the same URL or a modified URL. property | None¶ The registered name of the current blueprint. This will be None if the endpoint is not part of a blueprint, or if URL matching failed or has not been performed yet. This does not necessarily match the name the blueprint was created with. It may have been nested, or registered with a different name. property [str]¶ The registered names of the current blueprint upwards through parent blueprints. This will be an empty list if there is no current blueprint, or if URL matching failed. Changelog Added in version 2.0.1. on_json_loading_failed(e)¶ Called if get_json() fails and isn’t silenced. If this method returns a value, it is used as the return value for get_json(). The default implementation raises BadRequest. (ValueError | None) – If parsing failed, this is the exception. It will be None if the content type wasn’t application/json. Return Changelog Changed in version 2.3: Raise a 415 error instead of 400. property ¶ List of charsets this client supports as CharsetAccept object. property ¶ List of encodings this client accepts. Encodings in a HTTP term are compression encodings such as gzip. For charsets have a look at accept_charset. property ¶ List of languages this client accepts as LanguageAccept object. property ¶ List of mimetypes this client supports as MIMEAccept object. access_control_request_headers¶ Sent with a preflight request to indicate which headers will be sent with the cross origin request. Set access_control_allow_headers on the response to indicate which headers are allowed. access_control_request_method¶ Sent with a preflight request to indicate which method will be used for the cross origin request. Set access_control_allow_methods on the response to indicate which methods are allowed. property [str]¶ If a forwarded header exists this is a list of all ip addresses from the client ip to the last proxy server. classmethod application(f)¶ Decorate a function as responder that accepts the request as the last argument. This works like the responder() decorator but the function is passed the request object as the last argument and the request object will be closed automatically: @Request.application def my_wsgi_app(request): return Response('Hello World!') As of Werkzeug 0.14 HTTP exceptions are automatically caught and converted to responses instead of failing. (t.Callable[[Request], WSGIApplication]) – the WSGI callable to decorate new WSGI callable Return property [str, str]¶ The parsed URL parameters (the part in the URL after the question mark). By default an ImmutableMultiDict is returned from this function. This can be changed by setting parameter_storage_class to a different type. This might be necessary if the order of the form data is important. Changelog Changed in version 2.3: Invalid bytes remain percent encoded. property | None¶ The Authorization header parsed into an Authorization object. None if the header is not present. Changelog Changed in version 2.3: Authorization is no longer a dict. The token attribute was added for auth schemes that use a token instead of parameters. property ¶ Like url but without the query string. property ¶ A RequestCacheControl object for the incoming cache control headers. close()¶ Closes associated resources of this request object. This closes all file handles explicitly. You can also use the request object in a with statement which will automatically close it. Changelog Added in version 0.9. Return content_encoding¶ The Content-Encoding entity-header field is used as a modifier to the media-type. When present, its value indicates what additional content codings have been applied to the entity-body, and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field. Changelog Added in version 0.9. property | None¶ The Content-Length entity-header field indicates the size of the entity-body in bytes or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET. content_md5¶ The Content-MD5 entity-header field, as defined in RFC 1864, is an MD5 digest of the entity-body for the purpose of providing an end-to-end message integrity check (MIC) of the entity-body. (Note: a MIC is good for detecting accidental modification of the entity-body in transit, but is not proof against malicious attacks.) Changelog Added in version 0.9. content_type¶ The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET. property [str, str]¶ A dict with the contents of all cookies transmitted with the request. property ¶ The raw data read from stream. Will be empty if the request represents form data. To get the raw data even if it represents form data, use get_data(). date¶ The Date general-header field represents the date and time at which the message was originated, having the same semantics as orig-date in RFC 822. Changelog Changed in version 2.0: The datetime object is timezone-aware. dict_storage_class¶ alias of ImmutableMultiDict property [str, FileStorage]¶ MultiDict object containing all uploaded files. Each key in files is the name from the <input type=\"file\" name=\"\">. Each value in files is a Werkzeug FileStorage object. It basically behaves like a standard file object you know from Python, with the difference that it also has a save() function that can store the file on the filesystem. Note that files will only contain data if the request method was POST, PUT or PATCH and the <form> that posted to the request had enctype=\"multipart/form-data\". It will be empty otherwise. See the MultiDict / FileStorage documentation for more details about the used data structure. property [str, str]¶ The form parameters. By default an ImmutableMultiDict is returned from this function. This can be changed by setting parameter_storage_class to a different type. This might be necessary if the order of the form data is important. Please keep in mind that file uploads will not end up here, but instead in the files attribute. Changelog Changed in version 0.9: Previous to Werkzeug 0.9 this would only contain form data for POST and PUT requests. form_data_parser_class¶ alias of FormDataParser classmethod from_values(*args, **kwargs)¶ Create a new request object based on the values provided. If environ is given missing values are filled from there. This method is useful for small scripts when you need to simulate a request from an URL. Do not use this method for unittesting, there is a full featured client object (Client) that allows to create multipart requests, support for cookies etc. This accepts the same options as the EnvironBuilder. Changelog Changed in version 0.5: This method now accepts the same arguments as EnvironBuilder. Because of this the environ parameter is now called environ_overrides. object (Any) kwargs (Any) Return property ¶ Requested path, including the query string. get_data(cache=True, as_text=False, parse_form_data=False)¶ This reads the buffered incoming data from the client into one bytes object. By default this is cached but that behavior can be changed by setting cache to False. Usually it’s a bad idea to call this method without checking the content length first as a client could send dozens of megabytes or more to cause memory problems on the server. Note that if the form data was already parsed this method will not return anything as form data parsing does not cache the data like this method does. To implicitly invoke form data parsing function set parse_form_data to True. When this is done the return value of this method will be an empty string if the form parser handles the data. This generally is not necessary as if the whole data is cached (which is the default) the form parser will used the cached data to parse the form data. Please be generally aware of checking the content length first in any case before calling this method to avoid exhausting server memory. If as_text is set to True the return value will be a decoded string. Changelog Added in version 0.9. (bool) as_text (bool) parse_form_data (bool) Return | str get_json(force=False, silent=False, cache=True)¶ Parse data as JSON. If the mimetype does not indicate JSON (application/json, see is_json), or parsing fails, on_json_loading_failed() is called and its return value is used as the return value. By default this raises a 415 Unsupported Media Type resp. (bool) – Ignore the mimetype and always try to parse JSON. silent (bool) – Silence mimetype and parsing errors, and return None instead. cache (bool) – Store the parsed JSON to return for subsequent calls. Return | None Changelog Changed in version 2.3: Raise a 415 error instead of 400. Changed in version 2.1: Raise a 400 error if the content type is incorrect. property ¶ The host name the request was made to, including the port if it’s non-standard. Validated with trusted_hosts. See get_host() for a detailed explanation. property ¶ The request URL scheme and host only. property ¶ An object containing all the etags in the If-Match header. Return property | None¶ The parsed If-Modified-Since header as a datetime object. Changelog Changed in version 2.0: The datetime object is timezone-aware. property ¶ An object containing all the etags in the If-None-Match header. Return property ¶ The parsed If-Range header. Changelog Changed in version 2.0: IfRange.date is timezone-aware. Added in version 0.7. property | None¶ The parsed If-Unmodified-Since header as a datetime object. Changelog Changed in version 2.0: The datetime object is timezone-aware. input_stream¶ The raw WSGI input stream, without any safety checks. This is dangerous to use. It does not guard against infinite streams or reading past content_length or max_content_length. Use stream instead. property ¶ Check if the mimetype indicates JSON data, either application/json or application/*+json. is_multiprocess¶ boolean that is True if the application is served by a WSGI server that spawns multiple processes. is_multithread¶ boolean that is True if the application is served by a multithreaded WSGI server. is_run_once¶ boolean that is True if the application will be executed only once in a process lifetime. This is the case for CGI for example, but it’s not guaranteed that the execution only happens one time. property ¶ True if the request was made with a secure protocol (HTTPS or WSS). property ¶ The parsed JSON data if mimetype indicates JSON (application/json, see is_json). Calls get_json() with default arguments. If the request content type is not application/json, this will raise a 415 Unsupported Media Type error. Changelog Changed in version 2.3: Raise a 415 error instead of 400. Changed in version 2.1: Raise a 400 error if the content type is incorrect. list_storage_class¶ alias of ImmutableList make_form_data_parser()¶ Creates the form data parser. Instantiates the form_data_parser_class with some parameters. Changelog Added in version 0.8. Return max_forwards¶ The Max-Forwards request-header field provides a mechanism with the TRACE and OPTIONS methods to limit the number of proxies or gateways that can forward the request to the next inbound server. property ¶ Like content_type, but without parameters (eg, without charset, type etc.) and always lowercase. For example if the content type is text/HTML; charset=utf-8 the mimetype would be 'text/html'. property [str, str]¶ The mimetype parameters as dict. For example if the content type is text/html; charset=utf-8 the params would be {'charset': 'utf-8'}. origin¶ The host that the request originated from. Set access_control_allow_origin on the response to indicate which origins are allowed. parameter_storage_class¶ alias of ImmutableMultiDict property ¶ The Pragma general-header field is used to include implementation-specific directives that might apply to any recipient along the request/response chain. All pragma directives specify optional behavior from the viewpoint of the protocol; however, some systems MAY require that behavior be consistent with the directives. property | None¶ The parsed Range header. Changelog Added in version 0.7. Return referrer¶ The Referer[sic] request-header field allows the client to specify, for the server’s benefit, the address (URI) of the resource from which the Request-URI was obtained (the “referrer”, although the header field is misspelled). remote_user¶ If the server supports user authentication, and the script is protected, this attribute contains the username the user has authenticated as. property ¶ The request URL scheme, host, and root path. This is the root that the application is accessed from. property ¶ Alias for self.root_path. environ[\"SCRIPT_NAME\"] without a trailing slash. property [bytes]¶ The WSGI input stream, with safety checks. This stream can only be consumed once. Use get_data() to get the full data as bytes or text. The data attribute will contain the full bytes only if they do not represent form data. The form attribute will contain the parsed form data in that case. Unlike input_stream, this stream guards against infinite streams or reading past content_length or max_content_length. If max_content_length is set, it can be enforced on streams if wsgi.input_terminated is set. Otherwise, an empty stream is returned. If the limit is reached before the underlying stream is exhausted (such as a file that is too large, or an infinite stream), the remaining contents of the stream cannot be read safely. Depending on how the server handles this, clients may show a “connection reset” failure instead of seeing the 413 response. Changelog Changed in version 2.3: Check max_content_length preemptively and while reading. Changed in version 0.9: The stream is always set (but may be consumed) even if form parsing was accessed first. [str] | None = None¶ Valid host names when handling requests. By default all hosts are trusted, which means that whatever the client says the host is will be accepted. Because Host and X-Forwarded-Host headers can be set to any value by a malicious client, it is recommended to either set this property or implement similar validation in the proxy (if the application is being run behind one). Changelog Added in version 0.9. property ¶ The full request URL with the scheme, host, root path, path, and query string. property ¶ Alias for root_url. The URL with scheme, host, and root path. For example, https://example.com/app/. property ¶ The user agent. Use user_agent.string to get the header value. Set user_agent_class to a subclass of UserAgent to provide parsing for the other properties or other extended data. Changelog Changed in version 2.1: The built-in parser was removed. Set user_agent_class to a UserAgent subclass to parse data from the string. user_agent_class¶ alias of UserAgent property [str, str]¶ A werkzeug.datastructures.CombinedMultiDict that combines args and form. For GET requests, only args are present, not form. Changelog Changed in version 2.0: For GET requests, only args are present, not form. property ¶ True if the request method carries content. By default this is true if a Content-Type is sent. Changelog Added in version 0.8. ¶ The WSGI environment containing HTTP headers and information from the WSGI server. ¶ Set when creating the request object. If True, reading from the request body will cause a RuntimeException. Useful to prevent modifying the stream from middleware. method¶ The method the request was made with, such as GET. scheme¶ The URL scheme of the protocol the request used, such as https or wss. server¶ The address of the server. (host, port), (path, None) for unix sockets, or None if not known. root_path¶ The prefix that the application is mounted under, without a trailing slash. path comes after this. path¶ The path part of the URL after root_path. This is the path used for routing within the application. query_string¶ The part of the URL after the “?”. This is the raw value, use args for the parsed values. headers¶ The headers received with the request. remote_addr¶ The address of the client sending the request. flask.request¶ To access incoming request data, you can use the global request object. Flask parses incoming request data for you and gives you access to it through that global object. Internally Flask makes sure that you always get the correct data for the active thread if you are in a multithreaded environment. This is a proxy. See Notes On Proxies for more information. The request object is an instance of a Request. Response Objects¶ class flask.Response(response=None, status=None, headers=None, mimetype=None, content_type=None, direct_passthrough=False)¶ The response object that is used by default in Flask. Works like the response object from Werkzeug but is set to have an HTML mimetype by default. Quite often you don’t have to create this object yourself because make_response() will take care of that for you. If you want to replace the response object used you can subclass this and set response_class to your subclass. Changelog Changed in version 1.0: JSON support is added to the response, like the request. This is useful when testing to get the test client response data as JSON. Changed in version 1.0: Added max_cookie_size. (Iterable[str] | Iterable[bytes]) status (int | str | HTTPStatus | None) headers (Headers) mimetype (str | None) content_type (str | None) direct_passthrough (bool) | None = 'text/html'¶ the default mimetype if none is provided. accept_ranges¶ The Accept-Ranges header. Even though the name would indicate that multiple values are supported, it must be one string token only. The values 'bytes' and 'none' are common. Changelog Added in version 0.7. property ¶ Whether credentials can be shared by the browser to JavaScript code. As part of the preflight request it indicates whether credentials can be used on the cross origin request. access_control_allow_headers¶ Which headers can be sent with the cross origin request. access_control_allow_methods¶ Which methods can be used for the cross origin request. access_control_allow_origin¶ The origin or ‘*’ for any origin that may make cross origin requests. access_control_expose_headers¶ Which headers can be shared by the browser to JavaScript code. access_control_max_age¶ The maximum age in seconds the access control settings can be cached for. add_etag(overwrite=False, weak=False)¶ Add an etag for the current response if there is none yet. Changelog Changed in version 2.0: SHA-1 is used to generate the value. MD5 may not be available in some environments. (bool) weak (bool) Return age¶ The Age response-header field conveys the sender’s estimate of the amount of time since the response (or its revalidation) was generated at the origin server. Age values are non-negative decimal integers, representing time in seconds. property ¶ The Allow entity-header field lists the set of methods supported by the resource identified by the Request-URI. The purpose of this field is strictly to inform the recipient of valid methods associated with the resource. An Allow header field MUST be present in a 405 (Method Not Allowed) response. automatically_set_content_length = True¶ Should this response object automatically set the content-length header if possible? This is true by default. Changelog Added in version 0.8. property ¶ The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain. calculate_content_length()¶ Returns the content length if available or None otherwise. Return | None call_on_close(func)¶ Adds a function to the internal list of functions that should be called as part of closing down the response. Since 0.7 this function also returns the function that was passed so that this can be used as a decorator. Changelog Added in version 0.6. (Callable[[], Any]) Return [[], Any] close()¶ Close the wrapped response if possible. You can also use the object in a with statement which will automatically close it. Changelog Added in version 0.9: Can now be used in a with statement. Return content_encoding¶ The Content-Encoding entity-header field is used as a modifier to the media-type. When present, its value indicates what additional content codings have been applied to the entity-body, and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field. property ¶ The Content-Language entity-header field describes the natural language(s) of the intended audience for the enclosed entity. Note that this might not be equivalent to all the languages used within the entity-body. content_length¶ The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET. content_location¶ The Content-Location entity-header field MAY be used to supply the resource location for the entity enclosed in the message when that entity is accessible from a location separate from the requested resource’s URI. content_md5¶ The Content-MD5 entity-header field, as defined in RFC 1864, is an MD5 digest of the entity-body for the purpose of providing an end-to-end message integrity check (MIC) of the entity-body. (Note: a MIC is good for detecting accidental modification of the entity-body in transit, but is not proof against malicious attacks.) property ¶ The Content-Range header as a ContentRange object. Available even if the header is not set. Changelog Added in version 0.7. property ¶ The Content-Security-Policy header as a ContentSecurityPolicy object. Available even if the header is not set. The Content-Security-Policy header adds an additional layer of security to help detect and mitigate certain types of attacks. property ¶ The Content-Security-policy-report-only header as a ContentSecurityPolicy object. Available even if the header is not set. The Content-Security-Policy-Report-Only header adds a csp policy that is not enforced but is reported thereby helping detect certain types of attacks. content_type¶ The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET. cross_origin_embedder_policy¶ Prevents a document from loading any cross-origin resources that do not explicitly grant the document permission. Values must be a member of the werkzeug.http.COEP enum. cross_origin_opener_policy¶ Allows control over sharing of browsing context group with cross-origin documents. Values must be a member of the werkzeug.http.COOP enum. property | str¶ A descriptor that calls get_data() and set_data(). date¶ The Date general-header field represents the date and time at which the message was originated, having the same semantics as orig-date in RFC 822. Changelog Changed in version 2.0: The datetime object is timezone-aware. default_status = 200¶ the default status if none is provided. delete_cookie(key, path='/', domain=None, secure=False, httponly=False, samesite=None, partitioned=False)¶ Delete a cookie. Fails silently if key doesn’t exist. (str) – the key (name) of the cookie to be deleted. path (str | None) – if the cookie that should be deleted was limited to a path, the path has to be defined here. domain (str | None) – if the cookie that should be deleted was limited to a domain, that domain has to be defined here. secure (bool) – If True, the cookie will only be available via HTTPS. httponly (bool) – Disallow JavaScript access to the cookie. samesite (str | None) – Limit the scope of the cookie to only be attached to requests that are “same-site”. partitioned (bool) – If True, the cookie will be partitioned. Return expires¶ The Expires entity-header field gives the date/time after which the response is considered stale. A stale cache entry may not normally be returned by a cache. Changelog Changed in version 2.0: The datetime object is timezone-aware. classmethod force_type(response, environ=None)¶ Enforce that the WSGI response is a response object of the current type. Werkzeug will use the Response internally in many situations like the exceptions. If you call get_response() on an exception you will get back a regular Response object, even if you are using a custom subclass. This method can enforce a given response type, and it will also convert arbitrary WSGI callables into response objects if an environ is provided: # convert a Werkzeug response object into an instance of the # MyResponseClass subclass. response = MyResponseClass.force_type(response) # convert any WSGI application into a response object response = MyResponseClass.force_type(response, environ) This is especially useful if you want to post-process responses in the main dispatcher and use functionality provided by your subclass. Keep in mind that this will modify response objects in place if possible! (Response) – a response object or wsgi application. environ (WSGIEnvironment | None) – a WSGI environment object. response object. Return freeze()¶ Make the response object ready to be pickled. Does the the response into a list, ignoring implicity_sequence_conversion and direct_passthrough. Set the Content-Length header. Generate an ETag header if one is not already set. Changelog Changed in version 2.1: Removed the no_etag parameter. Changed in version 2.0: An ETag header is always added. Changed in version 0.6: The Content-Length header is set. Return classmethod from_app(app, environ, buffered=False)¶ Create a new response object from an application output. This works best if you pass it an application that returns a generator all the time. Sometimes applications may use the write() callable returned by the start_response function. This tries to resolve such edge cases automatically. But if you don’t get the expected output you should set buffered to True which enforces buffering. (WSGIApplication) – the WSGI application to execute. environ (WSGIEnvironment) – the WSGI environment to execute against. buffered (bool) – set to True to enforce buffering. response object. Return get_app_iter(environ)¶ Returns the application iterator for the given environ. Depending on the request method and the current status code the return value might be an empty response rather than the one from the response. If the request method is HEAD or the status code is in a range where the HTTP specification requires an empty response, an empty iterable is returned. Changelog Added in version 0.6. (WSGIEnvironment) – the WSGI environment of the request. response iterable. Return [bytes] get_data(as_text=False)¶ The string representation of the response body. Whenever you call this property the response iterable is encoded and flattened. This can lead to unwanted behavior if you stream big data. This behavior can be disabled by setting implicit_sequence_conversion to False. If as_text is set to True the return value will be a decoded string. Changelog Added in version 0.9. (bool) Return | str get_etag()¶ Return a tuple in the form (etag, is_weak). If there is no ETag the return value is (None, None). Return [str, bool] | tuple[None, None] get_json(force=False, silent=False)¶ Parse data as JSON. Useful during testing. If the mimetype does not indicate JSON (application/json, see is_json), this returns None. Unlike Request.get_json(), the result is not cached. (bool) – Ignore the mimetype and always try to parse JSON. silent (bool) – Silence parsing errors and return None instead. Return | None get_wsgi_headers(environ)¶ This is automatically called right before the response is started and returns headers modified for the given environment. It returns a copy of the headers from the response with some modifications applied if necessary. For example the location header (if present) is joined with the root URL of the environment. Also the content length is automatically set to zero here for certain status codes. Changelog Changed in version 0.6: Previously that function was called fix_headers and modified the response object in place. Also since 0.6, IRIs in location and content-location headers are handled properly. Also starting with 0.6, Werkzeug will attempt to set the content length if it is able to figure it out on its own. This is the case if all the strings in the response iterable are already encoded and the iterable is buffered. (WSGIEnvironment) – the WSGI environment of the request. a new Headers object. Return get_wsgi_response(environ)¶ Returns the final WSGI response as tuple. The first item in the tuple is the application iterator, the second the status and the third the list of headers. The response returned is created specially for the given environment. For example if the request method in the WSGI environment is 'HEAD' the response will be empty and only the headers and status code will be present. Changelog Added in version 0.6. (WSGIEnvironment) – the WSGI environment of the request. (app_iter, status, headers) tuple. Return [t.Iterable[bytes], str, list[tuple[str, str]]] implicit_sequence_conversion = True¶ if set to False accessing properties on the response object will not try to consume the response iterator and convert it into a list. Changelog Added in version 0.6.2: That attribute was previously called implicit_seqence_conversion. (Notice the typo). If you did use this feature, you have to adapt your code to the name change. property ¶ Check if the mimetype indicates JSON data, either application/json or application/*+json. property ¶ If the iterator is buffered, this property will be True. A response object will consider an iterator to be buffered if the response attribute is a list or tuple. Changelog Added in version 0.6. property ¶ If the response is streamed (the response is not an iterable with a length information) this property is True. In this case streamed means that there is no information about the number of iterations. This is usually True if a generator is passed to the response object. This is useful for checking before applying some sort of post filtering that should not take place for streamed responses. iter_encoded()¶ Iter the response encoded with the encoding of the response. If the response object is invoked as WSGI application the return value of this method is used as application iterator unless direct_passthrough was activated. Return [bytes] property | None¶ The parsed JSON data if mimetype indicates JSON (application/json, see is_json). Calls get_json() with default arguments. last_modified¶ The Last-Modified entity-header field indicates the date and time at which the origin server believes the variant was last modified. Changelog Changed in version 2.0: The datetime object is timezone-aware. location¶ The Location response-header field is used to redirect the recipient to a location other than the Request-URI for completion of the request or identification of a new resource. make_conditional(request_or_environ, accept_ranges=False, complete_length=None)¶ Make the response conditional to the request. This method works best if an etag was defined for the response already. The add_etag method can be used to do that. If called without etag just the date header is set. This does nothing if the request method in the request or environ is anything but GET or HEAD. For optimal performance when handling range requests, it’s recommended that your response data object implements seekable, seek and tell methods as described by io.IOBase. Objects returned by wrap_file() automatically implement those methods. It does not remove the body of the response because that’s something the __call__() function does for us automatically. Returns self so that you can do return resp.make_conditional(req) but modifies the object in-place. (WSGIEnvironment | Request) – a request object or WSGI environment to be used to make the response conditional against. accept_ranges (bool | str) – This parameter dictates the value of Accept-Ranges header. If False (default), the header is not set. If True, it will be set to \"bytes\". If it’s a string, it will use this value. complete_length (int | None) – Will be used only in valid Range Requests. It will set Content-Range complete length value and compute Content-Length real value. This parameter is mandatory for successful Range Requests completion. if Range header could not be parsed or satisfied. Return Changelog Changed in version 2.0: Range processing is skipped if length is 0 instead of raising a 416 Range Not Satisfiable error. make_sequence()¶ Converts the response iterator in a list. By default this happens automatically if required. If implicit_sequence_conversion is disabled, this method is not automatically called and some properties might raise exceptions. This also encodes all the items. Changelog Added in version 0.6. Return property | None¶ The mimetype (content type without charset etc.) property [str, str]¶ The mimetype parameters as dict. For example if the content type is text/html; charset=utf-8 the params would be {'charset': 'utf-8'}. Changelog Added in version 0.5. property | None¶ The Retry-After response-header field can be used with a 503 (Service Unavailable) response to indicate how long the service is expected to be unavailable to the requesting client. Time in seconds until expiration or date. Changelog Changed in version 2.0: The datetime object is timezone-aware. set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None, partitioned=False)¶ Sets a cookie. A warning is raised if the size of the cookie header exceeds max_cookie_size, but the header will still be set. (str) – the key (name) of the cookie to be set. value (str) – the value of the cookie. max_age (timedelta | int | None) – should be a number of seconds, or None (default) if the cookie should last only as long as the client’s browser session. expires (str | datetime | int | float | None) – should be a datetime object or UNIX timestamp. path (str | None) – limits the cookie to a given path, per default it will span the whole domain. domain (str | None) – if you want to set a cross-domain cookie. For example, domain=\"example.com\" will set a cookie that is readable by the domain www.example.com, foo.example.com etc. Otherwise, a cookie will only be readable by the domain that set it. secure (bool) – If True, the cookie will only be available via HTTPS. httponly (bool) – Disallow JavaScript access to the cookie. samesite (str | None) – Limit the scope of the cookie to only be attached to requests that are “same-site”. partitioned (bool) – If True, the cookie will be partitioned. Return Changed in version 3.1: The partitioned parameter was added. set_data(value)¶ Sets a new string as response. The value must be a string or bytes. If a string is set it’s encoded to the charset of the response (utf-8 by default). Changelog Added in version 0.9. (bytes | str) Return set_etag(etag, weak=False)¶ Set the etag, and override the old one if there was one. (str) weak (bool) Return property ¶ The HTTP status code as a string. property ¶ The HTTP status code as a number. property ¶ The response iterable as write-only stream. property ¶ The Vary field value indicates the set of request-header fields that fully determines, while the response is fresh, whether a cache is permitted to use the response to reply to a subsequent request without revalidation. property ¶ The WWW-Authenticate header parsed into a WWWAuthenticate object. Modifying the object will modify the header value. This header is not set by default. To set this header, assign an instance of WWWAuthenticate to this attribute. response.www_authenticate = WWWAuthenticate( \"basic\", {\"realm\": \"Authentication Required\"} ) Multiple values for this header can be sent to give the client multiple options. Assign a list to set multiple headers. However, modifying the items in the list will not automatically update the header values, and accessing this attribute will only ever return the first value. To unset this header, assign None or use del. Changelog Changed in version 2.3: This attribute can be assigned to set the header. A list can be assigned to set multiple header values. Use del to unset the header. Changed in version 2.3: WWWAuthenticate is no longer a dict. The token attribute was added for auth challenges that use a token instead of parameters. [str] | t.Iterable[bytes]¶ The response body to send as the WSGI iterable. A list of strings or bytes represents a fixed-length response, any other iterable is a streaming response. Strings are encoded to bytes as UTF-8. Do not set to a plain string or bytes, that will cause sending the response to be very inefficient as it will iterate one byte at a time. direct_passthrough¶ Pass the response body directly through as the WSGI iterable. This can be used when the body is a binary file or other iterator of bytes, to skip some unnecessary checks. Use send_file() instead of setting this manually. autocorrect_location_header = False¶ If a redirect Location header is a relative URL, make it an absolute URL, including scheme and domain. Changelog Changed in version 2.1: This is disabled by default, so responses will send relative redirects. Added in version 0.8. property ¶ Read-only view of the MAX_COOKIE_SIZE config key. See max_cookie_size in Werkzeug’s docs. Sessions¶ If you have set Flask.secret_key (or configured it from SECRET_KEY) you can use sessions in Flask applications. A session makes it possible to remember information from one request to another. The way Flask does this is by using a signed cookie. The user can look at the session contents, but can’t modify it unless they know the secret key, so make sure to set that to something complex and unguessable. To access the current session you can use the session flask.session¶ The session object works pretty much like an ordinary dict, with the difference that it keeps track of modifications. This is a proxy. See Notes On Proxies for more information. The following attributes are ¶ True if the session is new, False otherwise. modified¶ True if the session object detected a modification. Be advised that modifications on mutable structures are not picked up automatically, in that situation you have to explicitly set the attribute to True yourself. Here an example: # this change is not picked up because a mutable object (here # a list) is changed. session['objects'].append(42) # so mark it as modified yourself session.modified = True permanent¶ If set to True the session lives for permanent_session_lifetime seconds. The default is 31 days. If set to False (which is the default) the session will be deleted when the user closes the browser. Session Interface¶ Changelog Added in version 0.8. The session interface provides a simple way to replace the session implementation that Flask is using. class flask.sessions.SessionInterface¶ The basic interface you have to implement in order to replace the default session interface which uses werkzeug’s securecookie implementation. The only methods you have to implement are open_session() and save_session(), the others have useful defaults which you don’t need to change. The session object returned by the open_session() method has to provide a dictionary like interface plus the properties and methods from the SessionMixin. We recommend just subclassing a dict and adding that Session(dict, SessionMixin): pass If open_session() returns None Flask will call into make_null_session() to create a session that acts as replacement if the session support cannot work because some requirement is not fulfilled. The default NullSession class that is created will complain that the secret key was not set. To replace the session interface on an application all you have to do is to assign flask.Flask.session_interface: app = Flask(__name__) app.session_interface = MySessionInterface() Multiple requests with the same session may be sent and handled concurrently. When implementing a new session interface, consider whether reads or writes to the backing store must be synchronized. There is no guarantee on the order in which the session for each request is opened or saved, it will occur in the order that requests begin and end processing. Changelog Added in version 0.8. null_session_class¶ make_null_session() will look here for the class that should be created when a null session is requested. Likewise the is_null_session() method will perform a typecheck against this type. alias of NullSession pickle_based = False¶ A flag that indicates if the session interface is pickle based. This can be used by Flask extensions to make a decision in regards to how to deal with the session object. Changelog Added in version 0.10. make_null_session(app)¶ Creates a null session which acts as a replacement object if the real session support could not be loaded due to a configuration error. This mainly aids the user experience because the job of the null session is to still support lookup without complaining but modifications are answered with a helpful error message of what failed. This creates an instance of null_session_class by default. (Flask) Return is_null_session(obj)¶ Checks if a given object is a null session. Null sessions are not asked to be saved. This checks if the object is an instance of null_session_class by default. (object) Return get_cookie_name(app)¶ The name of the session cookie. Uses``app.config[“SESSION_COOKIE_NAME”]``. (Flask) Return get_cookie_domain(app)¶ The value of the Domain parameter on the session cookie. If not set, browsers will only send the cookie to the exact domain it was set from. Otherwise, they will send it to any subdomain of the given value as well. Uses the SESSION_COOKIE_DOMAIN config. Changelog Changed in version 2.3: Not set by default, does not fall back to SERVER_NAME. (Flask) Return | None get_cookie_path(app)¶ Returns the path for which the cookie should be valid. The default implementation uses the value from the SESSION_COOKIE_PATH config var if it’s set, and falls back to APPLICATION_ROOT or uses / if it’s None. (Flask) Return get_cookie_httponly(app)¶ Returns True if the session cookie should be httponly. This currently just returns the value of the SESSION_COOKIE_HTTPONLY config var. (Flask) Return get_cookie_secure(app)¶ Returns True if the cookie should be secure. This currently just returns the value of the SESSION_COOKIE_SECURE setting. (Flask) Return get_cookie_samesite(app)¶ Return 'Strict' or 'Lax' if the cookie should use the SameSite attribute. This currently just returns the value of the SESSION_COOKIE_SAMESITE setting. (Flask) Return | None get_cookie_partitioned(app)¶ Returns True if the cookie should be partitioned. By default, uses the value of SESSION_COOKIE_PARTITIONED. Added in version 3.1. (Flask) Return get_expiration_time(app, session)¶ A helper method that returns an expiration date for the session or None if the session is linked to the browser session. The default implementation returns now + the permanent session lifetime configured on the application. (Flask) session (SessionMixin) Return | None should_set_cookie(app, session)¶ Used by session backends to determine if a Set-Cookie header should be set for this session cookie for this response. If the session has been modified, the cookie is set. If the session is permanent and the SESSION_REFRESH_EACH_REQUEST config is true, the cookie is always set. This check is usually skipped if the session was deleted. Changelog Added in version 0.11. (Flask) session (SessionMixin) Return open_session(app, request)¶ This is called at the beginning of each request, after pushing the request context, before matching the URL. This must return an object which implements a dictionary-like interface as well as the SessionMixin interface. This will return None to indicate that loading failed in some way that is not immediately an error. The request context will fall back to using make_null_session() in this case. (Flask) request (Request) Return | None save_session(app, session, response)¶ This is called at the end of each request, after generating a response, before removing the request context. It is skipped if is_null_session() returns True. (Flask) session (SessionMixin) response (Response) Return class flask.sessions.SecureCookieSessionInterface¶ The default session interface that stores sessions in signed cookies through the itsdangerous module. salt = 'cookie-session'¶ the salt that should be applied on top of the secret key for the signing of cookie based sessions. static digest_method(string=b'')¶ the hash function to use for the signature. The default is sha1 (bytes) Return key_derivation = 'hmac'¶ the name of the itsdangerous supported key derivation. The default is hmac. serializer = <flask.json.tag.TaggedJSONSerializer object>¶ A python serializer for the payload. The default is a compact JSON derived serializer with support for some extra Python types such as datetime objects or tuples. session_class¶ alias of SecureCookieSession open_session(app, request)¶ This is called at the beginning of each request, after pushing the request context, before matching the URL. This must return an object which implements a dictionary-like interface as well as the SessionMixin interface. This will return None to indicate that loading failed in some way that is not immediately an error. The request context will fall back to using make_null_session() in this case. (Flask) request (Request) Return | None save_session(app, session, response)¶ This is called at the end of each request, after generating a response, before removing the request context. It is skipped if is_null_session() returns True. (Flask) session (SessionMixin) response (Response) Return class flask.sessions.SecureCookieSession(initial=None)¶ Base class for sessions based on signed cookies. This session backend will set the modified and accessed attributes. It cannot reliably track whether a session is new (vs. empty), so new remains hard coded to False. (c.Mapping[str, t.Any] | None) modified = False¶ When data is changed, this is set to True. Only the session dictionary itself is tracked; if the session contains mutable data (for example a nested dict) then this must be set to True manually when modifying that data. The session cookie will only be written to the response if this is True. class flask.sessions.NullSession(initial=None)¶ Class used to generate nicer error messages if sessions are not available. Will still allow read-only access to the empty session but fail on setting. (c.Mapping[str, t.Any] | None) clear(*args, **kwargs)¶ Remove all items from the dict. (Any) kwargs (Any) Return pop(k[, d]) → v, remove specified key and return the corresponding value.¶ If the key is not found, return the default if given; otherwise, raise a KeyError. (Any) kwargs (Any) Return popitem(*args, **kwargs)¶ Remove and return a (key, value) pair as a 2-tuple. Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty. (Any) kwargs (Any) Return update([E, ]**F) → None. Update D from mapping/iterable E and F.¶ If E is present and has a ; renderChart(names, {{ axis_data|tojson }}); </script> flask.json.jsonify(*args, **kwargs)¶ Serialize the given arguments as JSON, and return a Response object with the application/json mimetype. A dict or list returned from a view will be converted to a JSON response automatically without needing to call this. This requires an active request or application context, and calls app.json.response(). In debug mode, the output is formatted with indentation to make it easier to read. This may also be controlled by the provider. Either positional or keyword arguments can be given, not both. If no arguments are given, None is serialized. (t.Any) – A single value to serialize, or multiple values to treat as a list to serialize. kwargs (t.Any) – Treat as a dict to serialize. Return Changelog Changed in version 2.2: Calls current_app.json.response, allowing an app to override the behavior. Changed in version 2.0.2: decimal.Decimal is supported by converting to a string. Changed in version 0.11: Added support for serializing top-level arrays. This was a security risk in ancient browsers. See JSON Security. Added in version 0.2. flask.json.dumps(obj, **kwargs)¶ Serialize data as JSON. If current_app is available, it will use its app.json.dumps() method, otherwise it will use json.dumps(). (Any) – The data to serialize. kwargs (Any) – Arguments passed to the dumps implementation. Return Changelog Changed in version 2.3: The app parameter was removed. Changed in version 2.2: Calls current_app.json.dumps, allowing an app to override the behavior. Changed in version 2.0.2: decimal.Decimal is supported by converting to a string. Changed in version 2.0: encoding will be removed in Flask 2.1. Changed in version 1.0.3: app can be passed directly, rather than requiring an app context for configuration. flask.json.dump(obj, fp, **kwargs)¶ Serialize data as JSON and write to a file. If current_app is available, it will use its app.json.dump() method, otherwise it will use json.dump(). (Any) – The data to serialize. fp (IO[str]) – A file opened for writing text. Should use the UTF-8 encoding to be valid JSON. kwargs (Any) – Arguments passed to the dump implementation. Return Changelog Changed in version 2.3: The app parameter was removed. Changed in version 2.2: Calls current_app.json.dump, allowing an app to override the behavior. Changed in version 2.0: Writing to a binary file, and the encoding argument, will be removed in Flask 2.1. flask.json.loads(s, **kwargs)¶ Deserialize data as JSON. If current_app is available, it will use its app.json.loads() method, otherwise it will use json.loads(). (str | bytes) – Text or UTF-8 bytes. kwargs (Any) – Arguments passed to the loads implementation. Return Changelog Changed in version 2.3: The app parameter was removed. Changed in version 2.2: Calls current_app.json.loads, allowing an app to override the behavior. Changed in version 2.0: encoding will be removed in Flask 2.1. The data must be a string or UTF-8 bytes. Changed in version 1.0.3: app can be passed directly, rather than requiring an app context for configuration. flask.json.load(fp, **kwargs)¶ Deserialize data as JSON read from a file. If current_app is available, it will use its app.json.load() method, otherwise it will use json.load(). (IO) – A file opened for reading text or UTF-8 bytes. kwargs (Any) – Arguments passed to the load implementation. Return Changelog Changed in version 2.3: The app parameter was removed. Changed in version 2.2: Calls current_app.json.load, allowing an app to override the behavior. Changed in version 2.2: The app parameter will be removed in Flask 2.3. Changed in version 2.0: encoding will be removed in Flask 2.1. The file must be text mode, or binary mode with UTF-8 bytes. class flask.json.provider.JSONProvider(app)¶ A standard set of JSON operations for an application. Subclasses of this can be used to customize JSON behavior or use different JSON libraries. To implement a provider for a specific library, subclass this base class and implement at least dumps() and loads(). All other methods have default implementations. To use a different provider, either subclass Flask and set json_provider_class to a provider class, or set app.json to an instance of the class. (App) – An application instance. This will be stored as a weakref.proxy on the _app attribute. Changelog Added in version 2.2. dumps(obj, **kwargs)¶ Serialize data as JSON. (Any) – The data to serialize. kwargs (Any) – May be passed to the underlying JSON library. Return dump(obj, fp, **kwargs)¶ Serialize data as JSON and write to a file. (Any) – The data to serialize. fp (IO[str]) – A file opened for writing text. Should use the UTF-8 encoding to be valid JSON. kwargs (Any) – May be passed to the underlying JSON library. Return loads(s, **kwargs)¶ Deserialize data as JSON. (str | bytes) – Text or UTF-8 bytes. kwargs (Any) – May be passed to the underlying JSON library. Return load(fp, **kwargs)¶ Deserialize data as JSON read from a file. (IO) – A file opened for reading text or UTF-8 bytes. kwargs (Any) – May be passed to the underlying JSON library. Return response(*args, **kwargs)¶ Serialize the given arguments as JSON, and return a Response object with the application/json mimetype. The jsonify() function calls this method for the current application. Either positional or keyword arguments can be given, not both. If no arguments are given, None is serialized. (t.Any) – A single value to serialize, or multiple values to treat as a list to serialize. kwargs (t.Any) – Treat as a dict to serialize. Return class flask.json.provider.DefaultJSONProvider(app)¶ Provide JSON operations using Python’s built-in json library. Serializes the following additional data and datetime.date are serialized to RFC 822 strings. This is the same as the HTTP date format. uuid.UUID is serialized to a string. dataclasses.dataclass is passed to dataclasses.asdict(). Markup (or any object with a __html__ method) will call the __html__ method to get a string. (App) static default(o)¶ Apply this function to any object that json.dumps() does not know how to serialize. It should return a valid JSON type or raise a TypeError. (Any) Return ensure_ascii = True¶ Replace non-ASCII characters with escape sequences. This may be more compatible with some clients, but can be disabled for better performance and size. sort_keys = True¶ Sort the keys in any serialized dicts. This may be useful for some caching situations, but can be disabled for better performance. When enabled, keys must all be strings, they are not converted before sorting. | None = None¶ If True, or None out of debug mode, the response() output will not add indentation, newlines, or spaces. If False, or None in debug mode, it will use a non-compact representation. mimetype = 'application/json'¶ The mimetype set in response(). dumps(obj, **kwargs)¶ Serialize data as JSON to a string. Keyword arguments are passed to json.dumps(). Sets some parameter defaults from the default, ensure_ascii, and sort_keys attributes. (Any) – The data to serialize. kwargs (Any) – Passed to json.dumps(). Return loads(s, **kwargs)¶ Deserialize data as JSON from a string or bytes. (str | bytes) – Text or UTF-8 bytes. kwargs (Any) – Passed to json.loads(). Return response(*args, **kwargs)¶ Serialize the given arguments as JSON, and return a Response object with it. The response mimetype will be “application/json” and can be changed with mimetype. If compact is False or debug mode is enabled, the output will be formatted to be easier to read. Either positional or keyword arguments can be given, not both. If no arguments are given, None is serialized. (t.Any) – A single value to serialize, or multiple values to treat as a list to serialize. kwargs (t.Any) – Treat as a dict to serialize. Return Tagged JSON¶ A compact representation for lossless serialization of non-standard JSON types. SecureCookieSessionInterface uses this to serialize the session data, but it may be useful in other places. It can be extended to support other types. class flask.json.tag.TaggedJSONSerializer¶ Serializer that uses a tag system to compactly represent objects that are not JSON types. Passed as the intermediate serializer to itsdangerous.Serializer. The following extra types are tuple bytes Markup UUID datetime default_tags = [<class 'flask.json.tag.TagDict'>, <class 'flask.json.tag.PassDict'>, <class 'flask.json.tag.TagTuple'>, <class 'flask.json.tag.PassList'>, <class 'flask.json.tag.TagBytes'>, <class 'flask.json.tag.TagMarkup'>, <class 'flask.json.tag.TagUUID'>, <class 'flask.json.tag.TagDateTime'>]¶ Tag classes to bind when creating the serializer. Other tags can be added later using register(). register(tag_class, force=False, index=None)¶ Register a new tag with this serializer. (type[JSONTag]) – tag class to register. Will be instantiated with this serializer instance. force (bool) – overwrite an existing tag. If false (default), a KeyError is raised. index (int | None) – index to insert the new tag in the tag order. Useful when the new tag is a special case of an existing tag. If None (default), the tag is appended to the end of the order. – if the tag key is already registered and force is not true. Return tag(value)¶ Convert a value to a tagged representation if necessary. (Any) Return untag(value)¶ Convert a tagged representation back to the original type. (dict[str, Any]) Return dumps(value)¶ Tag the value and dump it to a compact JSON string. (Any) Return loads(value)¶ Load data from a JSON string and deserialized any tagged objects. (str) Return class flask.json.tag.JSONTag(serializer)¶ Base class for defining type tags for TaggedJSONSerializer. (TaggedJSONSerializer) = ''¶ The tag to mark the serialized object with. If empty, this tag is only used as an intermediate step during tagging. check(value)¶ Check if the given value should be tagged by this tag. (Any) Return to_json(value)¶ Convert the Python object to an object that is a valid JSON type. The tag will be added later. (Any) Return to_python(value)¶ Convert the JSON representation back to the correct type. The tag will already be removed. (Any) Return tag(value)¶ Convert the value to a valid JSON type and add the tag structure around it. (Any) Return [str, Any] Let’s see an example that adds support for OrderedDict. Dicts don’t have an order in JSON, so to handle this we will dump the items as a list of [key, value] pairs. Subclass JSONTag and give it the new key ' od' to identify the type. The session serializer processes dicts first, so insert the new tag at the front of the order since OrderedDict must be processed before dict. from flask.json.tag import JSONTag class TagOrderedDict(JSONTag): __slots__ = ('serializer',) key = ' od' def check(self, value): return isinstance(value, OrderedDict) def to_json(self, value): return [[k, self.serializer.tag(v)] for k, v in iteritems(value)] def to_python(self, value): return OrderedDict(value) app.session_interface.serializer.register(TagOrderedDict, index=0) Template Rendering¶ flask.render_template(template_name_or_list, **context)¶ Render a template by name with the given context. (str | Template | list[str | Template]) – The name of the template to render. If a list is given, the first name to exist will be rendered. context (Any) – The variables to make available in the template. Return flask.render_template_string(source, **context)¶ Render a template from the given source string with the given context. (str) – The source code of the template to render. context (Any) – The variables to make available in the template. Return flask.stream_template(template_name_or_list, **context)¶ Render a template by name with the given context as a stream. This returns an iterator of strings, which can be used as a streaming response from a view. (str | Template | list[str | Template]) – The name of the template to render. If a list is given, the first name to exist will be rendered. context (Any) – The variables to make available in the template. Return [str] Changelog Added in version 2.2. flask.stream_template_string(source, **context)¶ Render a template from the given source string with the given context as a stream. This returns an iterator of strings, which can be used as a streaming response from a view. (str) – The source code of the template to render. context (Any) – The variables to make available in the template. Return [str] Changelog Added in version 2.2. flask.get_template_attribute(template_name, attribute)¶ Loads a macro (or variable) a template exports. This can be used to invoke a macro from within Python code. If you for example have a template named _cider.html with the following contents: {% macro hello(name) %}Hello {{ name }}!{% endmacro %} You can access this from Python code like = get_template_attribute('_cider.html', 'hello') return hello('World') Changelog Added in version 0.2. (str) – the name of the template attribute (str) – the name of the variable of macro to access Return Configuration¶ class flask.Config(root_path, defaults=None)¶ Works exactly like a dict but provides ways to fill it from files or special dictionaries. There are two common patterns to populate the config. Either you can fill the config from a config ('yourconfig.cfg') Or alternatively you can define the configuration options in the module that calls from_object() or provide an import path to a module that should be loaded. It is also possible to tell it to use the same module and with that provide the configuration values just before the = True SECRET_KEY = 'development key' app.config.from_object(__name__) In both cases (loading from any Python file or loading from modules), only uppercase keys are added to the config. This makes it possible to use lowercase values in the config file for temporary values that are not added to the config or to define the config keys in the same file that implements the application. Probably the most interesting way to load configurations is from an environment variable pointing to a ('YOURAPPLICATION_SETTINGS') In this case before launching the application you have to set this environment variable to the file you want to use. On Linux and OS X use the export YOURAPPLICATION_SETTINGS='/path/to/config/file' On windows use set instead. (str | os.PathLike[str]) – path to which files are read relative from. When the config object is created by the application, this is the application’s root_path. defaults (dict[str, t.Any] | None) – an optional dictionary of default values from_envvar(variable_name, silent=False)¶ Loads a configuration from an environment variable pointing to a configuration file. This is basically just a shortcut with nicer error messages for this line of (os.environ['YOURAPPLICATION_SETTINGS']) (str) – name of the environment variable silent (bool) – set to True if you want silent failure for missing files. if the file was loaded successfully. Return from_prefixed_env(prefix='FLASK', *, loads=json.loads)¶ Load any environment variables that start with FLASK_, dropping the prefix from the env key for the config key. Values are passed through a loading function to attempt to convert them to more specific types than strings. Keys are loaded in sorted() order. The default loading function attempts to parse values as any valid JSON type, including dicts and lists. Specific items in nested dicts can be set by separating the keys with double underscores (__). If an intermediate key doesn’t exist, it will be initialized to an empty dict. (str) – Load env vars that start with this prefix, separated with an underscore (_). loads (Callable[[str], Any]) – Pass each string value to this function and use the returned value as the config value. If any error is raised it is ignored and the value remains a string. The default is json.loads(). Return Changelog Added in version 2.1. from_pyfile(filename, silent=False)¶ Updates the values in the config from a Python file. This function behaves as if the file was imported as module with the from_object() function. (str | PathLike[str]) – the filename of the config. This can either be an absolute filename or a filename relative to the root path. silent (bool) – set to True if you want silent failure for missing files. if the file was loaded successfully. Return Changelog Added in version 0.7: silent parameter. from_object(obj)¶ Updates the values from the given object. An object can be of one of the following two this case the object with that name will be imported an actual object object is used directly Objects are usually either modules or classes. from_object() loads only the uppercase attributes of the module/class. A dict object will not work with from_object() because the keys of a dict are not attributes of the dict class. Example of module-based ('yourapplication.default_config') from yourapplication import default_config app.config.from_object(default_config) Nothing is done to the object before loading. If the object is a class and has This is often useful when configuration options map directly to keyword arguments in functions or class constructors. (str) – a configuration namespace lowercase (bool) – a flag indicating if the keys of the resulting dictionary should be lowercase trim_namespace (bool) – a flag indicating if the keys of the resulting dictionary should not include the namespace Return [str, Any] Changelog Added in version 0.11. Stream Helpers¶ flask.stream_with_context(generator_or_function: Iterator) → Iterator¶ flask.stream_with_context(generator_or_function: Callable[[...], Iterator]) → Callable[[Iterator], Iterator] Wrap a response generator function so that it runs inside the current request context. This keeps request, session, and g available, even though at the point the generator runs the request context will typically have ended. Warning Due to the following caveat, it is often safer to pass the data you need as arguments to the generator, rather than relying on the context objects. More headers cannot be sent after the body has begun. Therefore, you must make sure all headers are set before starting the response. In particular, if the generator will access session, be sure to do so in the view as well so that the header will be set. Do not modify the session in the generator, as the Set-Cookie header will already be sent. Use it as a decorator on a generator flask import stream_with_context, request, Response @app.get(\"/stream\") def streamed_response(): @stream_with_context def generate(): yield \"Hello \" yield request.args[\"name\"] yield \"!\" return Response(generate()) Or use it as a wrapper around a created flask import stream_with_context, request, Response @app.get(\"/stream\") def streamed_response(): def generate(): yield \"Hello \" yield request.args[\"name\"] yield \"!\" return Response(stream_with_context(generate())) Changelog Added in version 0.9. Useful Internals¶ class flask.ctx.RequestContext(app, environ, request=None, session=None)¶ The request context contains per-request information. The Flask app creates and pushes it at the beginning of the request, then pops it at the end of the request. It will create the URL adapter and request object for the WSGI environment provided. Do not attempt to use this class directly, instead use test_request_context() and request_context() to create this object. When the request context is popped, it will evaluate all the functions registered on the application for teardown execution (teardown_request()). The request context is automatically popped at the end of the request. When using the interactive debugger, the context will be restored so request is still accessible. Similarly, the test client can preserve the context after the request ends. However, teardown functions may already have closed some resources such as database connections. (Flask) environ (WSGIEnvironment) request (Request | None) session (SessionMixin | None) copy()¶ Creates a copy of this request context with the same request object. This can be used to move a request context to a different greenlet. Because the actual request object is the same this cannot be used to move a request context to a different thread unless access to the request object is locked. Changelog Changed in version 1.1: The current session object is used instead of reloading the original data. This prevents flask.session pointing to an out-of-date object. Added in version 0.10. Return match_request()¶ Can be overridden by a subclass to hook into the matching of the request. Return property ¶ The session data associated with this request. Not available until this context has been pushed. Accessing this property, also accessed by the session proxy, sets SessionMixin.accessed. pop(exc=_sentinel)¶ Pops the request context and unbinds it by doing that. This will also trigger the execution of functions registered by the teardown_request() decorator. Changelog Changed in version 0.9: Added the exc argument. (BaseException | None) Return flask.globals.request_ctx¶ The current RequestContext. If a request context is not active, accessing attributes on this proxy will raise a RuntimeError. This is an internal object that is essential to how Flask handles requests. Accessing this should not be needed in most cases. Most likely you want request and session instead. class flask.ctx.AppContext(app)¶ The app context contains application-specific information. An app context is created and pushed at the beginning of each request if one is not already active. An app context is also pushed when running CLI commands. (Flask) push()¶ Binds the app context to the current context. Return pop(exc=_sentinel)¶ Pops the app context. (BaseException | None) Return flask.globals.app_ctx¶ The current AppContext. If an app context is not active, accessing attributes on this proxy will raise a RuntimeError. This is an internal object that is essential to how Flask handles requests. Accessing this should not be needed in most cases. Most likely you want current_app and g instead. class flask.blueprints.BlueprintSetupState(blueprint, app, options, first_registration)¶ Temporary holder object for registering a blueprint with the application. An instance of this class is created by the make_setup_state() method and later passed to all register callback functions. (Blueprint) app (App) options (t.Any) first_registration (bool) app¶ a reference to the current application blueprint¶ a reference to the blueprint that created this setup state. options¶ a dictionary with all options that were passed to the register_blueprint() method. first_registration¶ as blueprints can be registered multiple times with the application and not everything wants to be registered multiple times on it, this attribute can be used to figure out if the blueprint was registered in the past already. subdomain¶ The subdomain that the blueprint should be active for, None otherwise. url_prefix¶ The prefix that should be used for all URLs defined on the blueprint. url_defaults¶ A dictionary with URL defaults that is added to each and every URL that was defined with the blueprint. add_url_rule(rule, endpoint=None, view_func=None, **options)¶ A helper method to register a rule (and optionally a view function) to the application. The endpoint is automatically prefixed with the blueprint’s name. (str) endpoint (str | None) view_func (ft.RouteCallable | None) options (t.Any) Return Signals¶ Signals are provided by the Blinker library. See Signals for an introduction. flask.template_rendered¶ This signal is sent when a template was successfully rendered. The signal is invoked with the instance of the template as template and the context as dictionary (named context). Example log_template_renders(sender, template, context, **extra): sender.logger.debug('Rendering template \"%s\" with context %s', template.name or 'string template', context) from flask import template_rendered template_rendered.connect(log_template_renders, app) flask.before_render_template This signal is sent before template rendering process. The signal is invoked with the instance of the template as template and the context as dictionary (named context). Example log_template_renders(sender, template, context, **extra): sender.logger.debug('Rendering template \"%s\" with context %s', template.name or 'string template', context) from flask import before_render_template before_render_template.connect(log_template_renders, app) flask.request_started¶ This signal is sent when the request context is set up, before any request processing happens. Because the request context is already bound, the subscriber can access the request with the standard global proxies such as request. Example log_request(sender, **extra): sender.logger.debug('Request context is set up') from flask import request_started request_started.connect(log_request, app) flask.request_finished¶ This signal is sent right before the response is sent to the client. It is passed the response to be sent named response. Example log_response(sender, response, **extra): sender.logger.debug('Request context is about to close down. ' 'Response: %s', response) from flask import request_finished request_finished.connect(log_response, app) flask.got_request_exception¶ This signal is sent when an unhandled exception happens during request processing, including when debugging. The exception is passed to the subscriber as exception. This signal is not sent for HTTPException, or other exceptions that have error handlers registered, unless the exception was raised from an error handler. This example shows how to do some extra logging if a theoretical SecurityException was flask import got_request_exception def log_security_exception(sender, exception, **extra): if not isinstance(exception, SecurityException): return security_logger.exception( f\"SecurityException at {request.url!r}\", exc_info=exception, ) got_request_exception.connect(log_security_exception, app) flask.request_tearing_down¶ This signal is sent when the request is tearing down. This is always called, even if an exception is caused. Currently functions listening to this signal are called after the regular teardown handlers, but this is not something you can rely on. Example close_db_connection(sender, **extra): session.close() from flask import request_tearing_down request_tearing_down.connect(close_db_connection, app) As of Flask 0.9, this will also be passed an exc keyword argument that has a reference to the exception that caused the teardown if there was one. flask.appcontext_tearing_down¶ This signal is sent when the app context is tearing down. This is always called, even if an exception is caused. Currently functions listening to this signal are called after the regular teardown handlers, but this is not something you can rely on. Example close_db_connection(sender, **extra): session.close() from flask import appcontext_tearing_down appcontext_tearing_down.connect(close_db_connection, app) This will also be passed an exc keyword argument that has a reference to the exception that caused the teardown if there was one. flask.appcontext_pushed¶ This signal is sent when an application context is pushed. The sender is the application. This is usually useful for unittests in order to temporarily hook in information. For instance it can be used to set a resource early onto the g object. Example contextlib import contextmanager from flask import appcontext_pushed @contextmanager def user_set(app, user): def handler(sender, **kwargs): g.user = user with appcontext_pushed.connected_to(handler, app): yield And in the test_user_me(self): with user_set(app, 'john'): c = app.test_client() resp = c.get('/users/me') assert resp.data == 'username=john' Changelog Added in version 0.10. flask.appcontext_popped¶ This signal is sent when an application context is popped. The sender is the application. This usually falls in line with the appcontext_tearing_down signal. Changelog Added in version 0.10. flask.message_flashed¶ This signal is sent when the application is flashing a message. The messages is sent as message keyword argument and the category as category. Example = [] def record(sender, message, category, **extra): recorded.append((message, category)) from flask import message_flashed message_flashed.connect(record, app) Changelog Added in version 0.10. Class-Based Views¶ Changelog Added in version 0.7. class flask.views.View¶ Subclass this class and override dispatch_request() to create a generic class-based view. Call as_view() to create a view function that creates an instance of the class with the given arguments and calls its dispatch_request method with any URL variables. See Class-based Views for a detailed guide. class Hello(View): init_every_request = False def dispatch_request(self, name): return f\"Hello, {name}!\" app.add_url_rule( \"/hello/<name>\", view_func=Hello.as_view(\"hello\") ) Set methods on the class to change what methods the view accepts. Set decorators on the class to apply a list of decorators to the generated view function. Decorators applied to the class itself will not be applied to the generated view function! Set init_every_request to False for efficiency, unless you need to store request-global data on self. [Collection[str] | None] = None¶ The methods this view is registered for. Uses the same default ([\"GET\", \"HEAD\", \"OPTIONS\"]) as route and add_url_rule by default. [bool | None] = None¶ Control whether the OPTIONS method is handled automatically. Uses the same default (True) as route and add_url_rule by default. [list[Callable[[...], Any]]] = []¶ A list of decorators to apply, in order, to the generated view function. Remember that @decorator syntax is applied bottom to top, so the first decorator in the list would be the bottom decorator. Changelog Added in version 0.8. [bool] = True¶ Create a new instance of this view class for every request by default. If a view subclass sets this to False, the same instance is used for every request. A single instance is more efficient, especially if complex setup is done during init. However, storing data on self is no longer safe across requests, and g should be used instead. Changelog Added in version 2.2. dispatch_request()¶ The actual view function behavior. Subclasses must override this and return a valid response. Any variables from the URL rule are passed as keyword arguments. Return classmethod as_view(name, *class_args, **class_kwargs)¶ Convert the class into a view function that can be registered for a route. By default, the generated view will create a new instance of the view class for every request and call its dispatch_request() method. If the view class sets init_every_request to False, the same instance will be used for every request. Except for name, all other arguments passed to this method are forwarded to the view class __init__ method. Changelog Changed in version 2.2: Added the init_every_request class attribute. (str) class_args (t.Any) class_kwargs (t.Any) Return class flask.views.MethodView¶ Dispatches request methods to the corresponding instance methods. For example, if you implement a get method, it will be used to handle GET requests. This can be useful for defining a REST API. methods is automatically set based on the methods defined on the class. See Class-based Views for a detailed guide. class CounterAPI(MethodView): def get(self): return str(session.get(\"counter\", 0)) def post(self): session[\"counter\"] = session.get(\"counter\", 0) + 1 return redirect(url_for(\"counter\")) app.add_url_rule( \"/counter\", view_func=CounterAPI.as_view(\"counter\") ) dispatch_request(**kwargs)¶ The actual view function behavior. Subclasses must override this and return a valid response. Any variables from the URL rule are passed as keyword arguments. (t.Any) Return URL Route Registrations¶ Generally there are three ways to define rules for the routing can use the flask.Flask.route() decorator. You can use the flask.Flask.add_url_rule() function. You can directly access the underlying Werkzeug routing system which is exposed as flask.Flask.url_map. Variable parts in the route can be specified with angular brackets (/user/<username>). By default a variable part in the URL accepts any string without a slash however a different converter can be specified as well by using <converter:name>. Variable parts are passed to the view function as keyword arguments. The following converters are accepts any text without a slash (the default) int accepts integers float like int but for floating point values path like the default but also accepts slashes any matches one of the items provided uuid accepts UUID strings Custom converters can be defined using flask.Flask.url_map. Here are some examples: @app.route('/') def index(): pass @app.route('/<username>') def show_user(username): pass @app.route('/post/<int:post_id>') def show_post(post_id): pass An important detail to keep in mind is how Flask deals with trailing slashes. The idea is to keep each URL unique so the following rules a rule ends with a slash and is requested without a slash by the user, the user is automatically redirected to the same page with a trailing slash attached. If a rule does not end with a trailing slash and the user requests the page with a trailing slash, a 404 not found is raised. This is consistent with how web servers deal with static files. This also makes it possible to use relative link targets safely. You can also define multiple rules for the same function. They have to be unique however. Defaults can also be specified. Here for example is a definition for a URL that accepts an optional page: @app.route('/users/', defaults={'page': 1}) @app.route('/users/page/<int:page>') def show_users(page): pass This specifies that /users/ will be the URL for page one and /users/page/N will be the URL for page N. If a URL contains a default value, it will be redirected to its simpler form with a 301 redirect. In the above example, /users/page/1 will be redirected to /users/. If your route handles GET and POST requests, make sure the default route only handles GET, as redirects can’t preserve form data. @app.route('/region/', defaults={'id': 1}) @app.route('/region/<int:id>', methods=['GET', 'POST']) def region(id): pass Here are the parameters that route() and add_url_rule() accept. The only difference is that with the route parameter the view function is defined with the decorator instead of the view_func parameter. rule the URL rule as string endpoint the endpoint for the registered URL rule. Flask itself assumes that the name of the view function is the name of the endpoint if not explicitly stated. view_func the function to call when serving a request to the provided endpoint. If this is not provided one can specify the function later by storing it in the view_functions dictionary with the endpoint as key. defaults A dictionary with defaults for this rule. See the example above for how defaults work. subdomain specifies the rule for the subdomain in case subdomain matching is in use. If not specified the default subdomain is assumed. **options the options to be forwarded to the underlying Rule object. A change to Werkzeug is handling of method options. methods is a list of methods this rule should be limited to (GET, POST etc.). By default a rule just listens for GET (and implicitly HEAD). Starting with Flask 0.6, OPTIONS is implicitly added and handled by the standard request handling. They have to be specified as keyword arguments. View Function Options¶ For internal usage the view functions can have some attributes attached to customize behavior the view function would normally not have control over. The following attributes can be provided optionally to either override some defaults to add_url_rule() or general : The name of a function is by default used as endpoint. If endpoint is provided explicitly this value is used. Additionally this will be prefixed with the name of the blueprint by default which cannot be customized from the function itself. methods are not provided when the URL rule is added, Flask will look on the view function object itself if a methods attribute exists. If it does, it will pull the information for the methods from there. this attribute is set Flask will either force enable or disable the automatic implementation of the HTTP OPTIONS response. This can be useful when working with decorators that want to customize the OPTIONS response on a per-view basis. this attribute is set, Flask will always add these methods when registering a URL rule even if the methods were explicitly overridden in the route() call. Full index(): if request.method == 'OPTIONS': # custom options handling here ... return 'Hello World!' index.provide_automatic_options = False index.methods = ['GET', 'OPTIONS'] app.add_url_rule('/', index) Changelog Added in version 0.8: The provide_automatic_options functionality was added. Command Line Interface¶ class flask.cli.FlaskGroup(add_default_commands=True, create_app=None, add_version_option=True, load_dotenv=True, set_debug_flag=True, **extra)¶ Special subclass of the AppGroup group that supports loading more commands from the configured Flask app. Normally a developer does not have to interface with this class but there are some very advanced use cases for which it makes sense to create an instance of this. see Custom Scripts. (bool) – if this is True then the default run and shell commands will be added. add_version_option (bool) – adds the --version option. create_app (t.Callable[..., Flask] | None) – an optional callback that is passed the script info and returns the loaded app. load_dotenv (bool) – Load the nearest .env and .flaskenv files to set environment variables. Will also change the working directory to the directory containing the first file found. set_debug_flag (bool) – Set the app’s debug flag. extra (t.Any) Changed in version 3.1: -e path takes precedence over default .env and .flaskenv files. Changelog Changed in version 2.2: Added the -A/--app, --debug/--no-debug, -e/--env-file options. Changed in version 2.2: An app context is pushed when running app.cli commands, so @with_appcontext is no longer required for those commands. Changed in version 1.0: If installed, python-dotenv will be used to load environment variables from .env and .flaskenv files. get_command(ctx, name)¶ Given a context and a command name, this returns a Command object if it exists or returns None. (Context) name (str) Return | None list_commands(ctx)¶ Returns a list of subcommand names in the order they should appear. (Context) Return [str] make_context(info_name, args, parent=None, **extra)¶ This function when given an info name and arguments will kick off the parsing and create a new Context. It does not invoke the actual command callback though. To quickly customize the context class used without overriding this method, set the context_class attribute. (str | None) – the info name for this invocation. Generally this is the most descriptive name for the script or command. For the toplevel script it’s usually the name of the script, for commands below it’s the name of the command. args (list[str]) – the arguments to parse as list of strings. parent (Context | None) – the parent context if available. extra (Any) – extra keyword arguments forwarded to the context constructor. Return Changed in version 8.0: Added the context_class attribute. class flask.cli.AppGroup(name=None, commands=None, invoke_without_command=False, no_args_is_help=None, subcommand_metavar=None, chain=False, result_callback=None, **kwargs)¶ This works similar to a regular click Group but it changes the behavior of the command() decorator so that it automatically wraps the functions in with_appcontext(). Not to be confused with FlaskGroup. (str | None) commands (MutableMapping[str, Command]) invoke_without_command (bool) no_args_is_help (bool) subcommand_metavar (str) chain (bool) result_callback (t.Callable[..., t.Any] | None) kwargs (t.Any) command(*args, **kwargs)¶ This works exactly like the method of the same name on a regular click.Group but it wraps callbacks in with_appcontext() unless it’s disabled by passing with_appcontext=False. (Any) kwargs (Any) Return [[Callable[[…], Any]], Command] group(*args, **kwargs)¶ This works exactly like the method of the same name on a regular click.Group but it defaults the group class to AppGroup. (Any) kwargs (Any) Return [[Callable[[…], Any]], Group] class flask.cli.ScriptInfo(app_import_path=None, create_app=None, set_debug_flag=True, load_dotenv_defaults=True)¶ Helper object to deal with Flask applications. This is usually not necessary to interface with as it’s used internally in the dispatching to click. In future versions of Flask this object will most likely play a bigger role. Typically it’s created automatically by the FlaskGroup but you can also manually create it and pass it onwards as click object. Changed in version 3.1: Added the load_dotenv_defaults parameter and attribute. (str | None) create_app (t.Callable[..., Flask] | None) set_debug_flag (bool) load_dotenv_defaults (bool) app_import_path¶ Optionally the import path for the Flask application. create_app¶ Optionally a function that is passed the script info to create the instance of the application. [t.Any, t.Any]¶ A dictionary with arbitrary data that can be associated with this script info. load_dotenv_defaults¶ Whether default .flaskenv and .env files should be loaded. ScriptInfo doesn’t load anything, this is for reference when doing the load elsewhere during processing. Added in version 3.1. load_app()¶ Loads the Flask app (if not yet loaded) and returns it. Calling this multiple times will just result in the already loaded app to be returned. Return flask.cli.load_dotenv(path=None, load_defaults=True)¶ Load “dotenv” files to set environment variables. A given path takes precedence over .env, which takes precedence over .flaskenv. After loading and combining these files, values are only set if the key is not already set in os.environ. This is a no-op if python-dotenv is not installed. (str | PathLike[str] | None) – Load the file at this location. load_defaults (bool) – Search for and load the default .flaskenv and .env files. if at least one env var was loaded. Return Changed in version 3.1: Added the load_defaults parameter. A given path takes precedence over default files. Changelog Changed in version 2.0: The current directory is not changed to the location of the loaded file. Changed in version 2.0: When loading the env files, set the default encoding to UTF-8. Changed in version 1.1.0: Returns False when python-dotenv is not installed, or when the given path isn’t a file. Added in version 1.0. flask.cli.with_appcontext(f)¶ Wraps a callback so that it’s guaranteed to be executed with the script’s application context. Custom commands (and their options) registered under app.cli or blueprint.cli will always have an app context available, this decorator is not required in that case. Changelog Changed in version 2.2: The app context is active for subcommands as well as the decorated callback. The app context is always available to app.cli command and parameter callbacks. (F) Return flask.cli.pass_script_info(f)¶ Marks a function so that an instance of ScriptInfo is passed as first argument to the click callback. (t.Callable[te.Concatenate[T, P], R]) Return [P, R] flask.cli.run_command = <Command run>¶ Run a local development server. This server is for development purposes only. It does not provide the stability, security, or performance of production WSGI servers. The reloader and debugger are enabled by default with the ‘–debug’ option. (t.Any) kwargs (t.Any) Return flask.cli.shell_command = <Command shell>¶ Run an interactive Python shell in the context of a given Flask application. The application will populate the default namespace of this shell according to its configuration. This is useful for executing small snippets of management code without having to manually configure the application. (t.Any) kwargs (t.Any) Return Contents API Application Object Flask Flask.request_class Flask.response_class Flask.session_interface Flask.cli Flask.get_send_file_max_age() Flask.send_static_file() Flask.open_resource() Flask.open_instance_resource() Flask.create_jinja_environment() Flask.create_url_adapter() Flask.update_template_context() Flask.make_shell_context() Flask.run() Flask.test_client() Flask.test_cli_runner() Flask.handle_http_exception() Flask.handle_user_exception() Flask.handle_exception() Flask.log_exception() Flask.dispatch_request() Flask.full_dispatch_request() Flask.make_default_options_response() Flask.ensure_sync() Flask.async_to_sync() Flask.url_for() Flask.make_response() Flask.preprocess_request() Flask.process_response() Flask.do_teardown_request() Flask.do_teardown_appcontext() Flask.app_context() Flask.request_context() Flask.test_request_context() Flask.wsgi_app() Flask.aborter_class Flask.add_template_filter() Flask.add_template_global() Flask.add_template_test() Flask.add_url_rule() Flask.after_request() Flask.app_ctx_globals_class Flask.auto_find_instance_path() Flask.before_request() Flask.config_class Flask.context_processor() Flask.create_global_jinja_loader() Flask.debug Flask.delete() Flask.endpoint() Flask.errorhandler() Flask.get() Flask.handle_url_build_error() Flask.has_static_folder Flask.inject_url_defaults() Flask.iter_blueprints() Flask.jinja_env Flask.jinja_environment Flask.jinja_loader Flask.jinja_options Flask.json_provider_class Flask.logger Flask.make_aborter() Flask.make_config() Flask.name Flask.patch() Flask.permanent_session_lifetime Flask.post() Flask.put() Flask.redirect() Flask.register_blueprint() Flask.register_error_handler() Flask.route() Flask.secret_key Flask.select_jinja_autoescape() Flask.shell_context_processor() Flask.should_ignore_error() Flask.static_folder Flask.static_url_path Flask.teardown_appcontext() Flask.teardown_request() Flask.template_filter() Flask.template_global() Flask.template_test() Flask.test_cli_runner_class Flask.test_client_class Flask.testing Flask.trap_http_exception() Flask.url_defaults() Flask.url_map_class Flask.url_rule_class Flask.url_value_preprocessor() Flask.instance_path Flask.config Flask.aborter Flask.json Flask.url_build_error_handlers Flask.teardown_appcontext_funcs Flask.shell_context_processors Flask.blueprints Flask.extensions Flask.url_map Flask.import_name Flask.template_folder Flask.root_path Flask.view_functions Flask.error_handler_spec Flask.before_request_funcs Flask.after_request_funcs Flask.teardown_request_funcs Flask.template_context_processors Flask.url_value_preprocessors Flask.url_default_functions Blueprint Objects Blueprint Blueprint.cli Blueprint.get_send_file_max_age() Blueprint.send_static_file() Blueprint.open_resource() Blueprint.add_app_template_filter() Blueprint.add_app_template_global() Blueprint.add_app_template_test() Blueprint.add_url_rule() Blueprint.after_app_request() Blueprint.after_request() Blueprint.app_context_processor() Blueprint.app_errorhandler() Blueprint.app_template_filter() Blueprint.app_template_global() Blueprint.app_template_test() Blueprint.app_url_defaults() Blueprint.app_url_value_preprocessor() Blueprint.before_app_request() Blueprint.before_request() Blueprint.context_processor() Blueprint.delete() Blueprint.endpoint() Blueprint.errorhandler() Blueprint.get() Blueprint.has_static_folder Blueprint.jinja_loader Blueprint.make_setup_state() Blueprint.patch() Blueprint.post() Blueprint.put() Blueprint.record() Blueprint.record_once() Blueprint.register() Blueprint.register_blueprint() Blueprint.register_error_handler() Blueprint.route() Blueprint.static_folder Blueprint.static_url_path Blueprint.teardown_app_request() Blueprint.teardown_request() Blueprint.url_defaults() Blueprint.url_value_preprocessor() Blueprint.import_name Blueprint.template_folder Blueprint.root_path Blueprint.view_functions Blueprint.error_handler_spec Blueprint.before_request_funcs Blueprint.after_request_funcs Blueprint.teardown_request_funcs Blueprint.template_context_processors Blueprint.url_value_preprocessors Blueprint.url_default_functions Incoming Request Data Request Request.url_rule Request.view_args Request.routing_exception Request.max_content_length Request.max_form_memory_size Request.max_form_parts Request.endpoint Request.blueprint Request.blueprints Request.on_json_loading_failed() Request.accept_charsets Request.accept_encodings Request.accept_languages Request.accept_mimetypes Request.access_control_request_headers Request.access_control_request_method Request.access_route Request.application() Request.args Request.authorization Request.base_url Request.cache_control Request.close() Request.content_encoding Request.content_length Request.content_md5 Request.content_type Request.cookies Request.data Request.date Request.dict_storage_class Request.files Request.form Request.form_data_parser_class Request.from_values() Request.full_path Request.get_data() Request.get_json() Request.host Request.host_url Request.if_match Request.if_modified_since Request.if_none_match Request.if_range Request.if_unmodified_since Request.input_stream Request.is_json Request.is_multiprocess Request.is_multithread Request.is_run_once Request.is_secure Request.json Request.list_storage_class Request.make_form_data_parser() Request.max_forwards Request.mimetype Request.mimetype_params Request.origin Request.parameter_storage_class Request.pragma Request.range Request.referrer Request.remote_user Request.root_url Request.script_root Request.stream Request.trusted_hosts Request.url Request.url_root Request.user_agent Request.user_agent_class Request.values Request.want_form_data_parsed Request.environ Request.shallow Request.method Request.scheme Request.server Request.root_path Request.path Request.query_string Request.headers Request.remote_addr request Response Objects Response Response.default_mimetype Response.accept_ranges Response.access_control_allow_credentials Response.access_control_allow_headers Response.access_control_allow_methods Response.access_control_allow_origin Response.access_control_expose_headers Response.access_control_max_age Response.add_etag() Response.age Response.allow Response.automatically_set_content_length Response.cache_control Response.calculate_content_length() Response.call_on_close() Response.close() Response.content_encoding Response.content_language Response.content_length Response.content_location Response.content_md5 Response.content_range Response.content_security_policy Response.content_security_policy_report_only Response.content_type Response.cross_origin_embedder_policy Response.cross_origin_opener_policy Response.data Response.date Response.default_status Response.delete_cookie() Response.expires Response.force_type() Response.freeze() Response.from_app() Response.get_app_iter() Response.get_data() Response.get_etag() Response.get_json() Response.get_wsgi_headers() Response.get_wsgi_response() Response.implicit_sequence_conversion Response.is_json Response.is_sequence Response.is_streamed Response.iter_encoded() Response.json Response.last_modified Response.location Response.make_conditional() Response.make_sequence() Response.mimetype Response.mimetype_params Response.retry_after Response.set_cookie() Response.set_data() Response.set_etag() Response.status Response.status_code Response.stream Response.vary Response.www_authenticate Response.response Response.direct_passthrough Response.autocorrect_location_header Response.max_cookie_size Sessions session session.new session.modified session.permanent Session Interface SessionInterface SessionInterface.null_session_class SessionInterface.pickle_based SessionInterface.make_null_session() SessionInterface.is_null_session() SessionInterface.get_cookie_name() SessionInterface.get_cookie_domain() SessionInterface.get_cookie_path() SessionInterface.get_cookie_httponly() SessionInterface.get_cookie_secure() SessionInterface.get_cookie_samesite() SessionInterface.get_cookie_partitioned() SessionInterface.get_expiration_time() SessionInterface.should_set_cookie() SessionInterface.open_session() SessionInterface.save_session() SecureCookieSessionInterface SecureCookieSessionInterface.salt SecureCookieSessionInterface.digest_method() SecureCookieSessionInterface.key_derivation SecureCookieSessionInterface.serializer SecureCookieSessionInterface.session_class SecureCookieSessionInterface.open_session() SecureCookieSessionInterface.save_session() SecureCookieSession SecureCookieSession.modified NullSession NullSession.clear() NullSession.pop() NullSession.popitem() NullSession.update() NullSession.setdefault() SessionMixin SessionMixin.permanent SessionMixin.modified SessionMixin.accessed Test Client FlaskClient FlaskClient.session_transaction() FlaskClient.open() Test CLI Runner FlaskCliRunner FlaskCliRunner.invoke() Application Globals g _AppCtxGlobals _AppCtxGlobals.get() _AppCtxGlobals.pop() _AppCtxGlobals.setdefault() Useful Functions and Classes current_app has_request_context() copy_current_request_context() has_app_context() url_for() abort() redirect() make_response() after_this_request() send_file() send_from_directory() Message Flashing flash() get_flashed_messages() JSON Support jsonify() dumps() dump() loads() load() JSONProvider JSONProvider.dumps() JSONProvider.dump() JSONProvider.loads() JSONProvider.load() JSONProvider.response() DefaultJSONProvider DefaultJSONProvider.default() DefaultJSONProvider.ensure_ascii DefaultJSONProvider.sort_keys DefaultJSONProvider.compact DefaultJSONProvider.mimetype DefaultJSONProvider.dumps() DefaultJSONProvider.loads() DefaultJSONProvider.response() Tagged JSON TaggedJSONSerializer TaggedJSONSerializer.default_tags TaggedJSONSerializer.register() TaggedJSONSerializer.tag() TaggedJSONSerializer.untag() TaggedJSONSerializer.dumps() TaggedJSONSerializer.loads() JSONTag JSONTag.key JSONTag.check() JSONTag.to_json() JSONTag.to_python() JSONTag.tag() Template Rendering render_template() render_template_string() stream_template() stream_template_string() get_template_attribute() Configuration Config Config.from_envvar() Config.from_prefixed_env() Config.from_pyfile() Config.from_object() Config.from_file() Config.from_mapping() Config.get_namespace() Stream Helpers stream_with_context() Useful Internals RequestContext RequestContext.copy() RequestContext.match_request() RequestContext.session RequestContext.pop() flask.globals.request_ctx AppContext AppContext.push() AppContext.pop() flask.globals.app_ctx BlueprintSetupState BlueprintSetupState.app BlueprintSetupState.blueprint BlueprintSetupState.options BlueprintSetupState.first_registration BlueprintSetupState.subdomain BlueprintSetupState.url_prefix BlueprintSetupState.url_defaults BlueprintSetupState.add_url_rule() Signals template_rendered request_started request_finished got_request_exception request_tearing_down appcontext_tearing_down appcontext_pushed appcontext_popped message_flashed Class-Based Views View View.methods View.provide_automatic_options View.decorators View.init_every_request View.dispatch_request() View.as_view() MethodView MethodView.dispatch_request() URL Route Registrations View Function Options Command Line Interface FlaskGroup FlaskGroup.get_command() FlaskGroup.list_commands() FlaskGroup.make_context() AppGroup AppGroup.command() AppGroup.group() ScriptInfo ScriptInfo.app_import_path ScriptInfo.create_app ScriptInfo.data ScriptInfo.load_dotenv_defaults ScriptInfo.load_app() load_dotenv() with_appcontext() pass_script_info() run_command shell_command Navigation Overview async and await Decisions in Flask Quick search\n\nExample:\n```text\nfrom flask import Flask\napp = Flask(__name__)\n```\n\nExample:\n```text\napp = Flask('yourapplication')\napp = Flask(__name__.split('.')[0])\n```\n\nExample:\n```text\nwith app.open_resource(\"schema.sql\") as f:\n    conn.executescript(f.read())\n```\n\nExample:\n```text\napp.testing = True\nclient = app.test_client()\n```\n\nExample:\n```text\nwith app.test_client() as c:\n    rv = c.get('/?vodka=42')\n    assert request.args['vodka'] == '42'\n```\n\nExample:\n```text\nfrom flask.testing import FlaskClient\n\nclass CustomClient(FlaskClient):\n    def __init__(self, *args, **kwargs):\n        self._authentication = kwargs.pop(\"authentication\")\n        super(CustomClient,self).__init__( *args, **kwargs)\n\napp.test_client_class = CustomClient\nclient = app.test_client(authentication='Basic ....')\n```\n\nExample:\n```text\nresult = app.async_to_sync(func)(*args, **kwargs)\n```\n\nExample:\n```text\nwith app.app_context():\n    init_db()\n```\n\nExample:\n```text\nwith app.test_request_context(...):\n    generate_report()\n```\n\nExample:\n```text\nctx = app.test_request_context(...)\nctx.push()\n...\nctx.pop()\n```\n\nExample:\n```text\napp = MyMiddleware(app)\n```\n\nExample:\n```text\napp.wsgi_app = MyMiddleware(app.wsgi_app)\n```\n\nExample:\n```text\n@app.route(\"/\")\ndef index():\n    ...\n```\n\nExample:\n```text\ndef index():\n    ...\n\napp.add_url_rule(\"/\", view_func=index)\n```\n\nExample:\n```text\napp.add_url_rule(\"/\", endpoint=\"index\")\n\n@app.endpoint(\"index\")\ndef index():\n    ...\n```\n\nExample:\n```text\n@app.before_request\ndef load_user():\n    if \"user_id\" in session:\n        g.user = db.session.get(session[\"user_id\"])\n```\n\nExample:\n```text\napp.add_url_rule(\"/ex\", endpoint=\"example\")\n\n@app.endpoint(\"example\")\ndef example():\n    ...\n```\n\nExample:\n```text\n@app.errorhandler(404)\ndef page_not_found(error):\n    return 'This page does not exist', 404\n```\n\nExample:\n```text\n@app.errorhandler(DatabaseError)\ndef special_exception_handler(error):\n    return 'Database connection failed', 500\n```\n\nExample:\n```text\n@app.route(\"/\")\ndef index():\n    return \"Hello, World!\"\n```\n\nExample:\n```text\nwith app.app_context():\n    ...\n```\n\nExample:\n```text\nwith app.test_request_context():\n    ...\n```\n\nExample:\n```text\n@app.template_filter()\ndef reverse(s):\n    return s[::-1]\n```\n\nExample:\n```text\n@app.template_global()\ndef double(n):\n    return 2 * n\n```\n\nExample:\n```text\n@app.template_test()\ndef is_prime(n):\n    if n == 2:\n        return True\n    for i in range(2, int(math.ceil(math.sqrt(n))) + 1):\n        if n % i == 0:\n            return False\n    return True\n```\n\nExample:\n```text\nfrom werkzeug.routing import BaseConverter\n\nclass ListConverter(BaseConverter):\n    def to_python(self, value):\n        return value.split(',')\n    def to_url(self, values):\n        return ','.join(super(ListConverter, self).to_url(value)\n                        for value in values)\n\napp = Flask(__name__)\napp.url_map.converters['list'] = ListConverter\n```\n\nExample:\n```text\n@Request.application\ndef my_wsgi_app(request):\n    return Response('Hello World!')\n```\n\nExample:\n```text\n# convert a Werkzeug response object into an instance of the\n# MyResponseClass subclass.\nresponse = MyResponseClass.force_type(response)\n\n# convert any WSGI application into a response object\nresponse = MyResponseClass.force_type(response, environ)\n```\n\nExample:\n```text\nresponse.www_authenticate = WWWAuthenticate(\n    \"basic\", {\"realm\": \"Authentication Required\"}\n)\n```\n\nExample:\n```text\n# this change is not picked up because a mutable object (here\n# a list) is changed.\nsession['objects'].append(42)\n# so mark it as modified yourself\nsession.modified = True\n```\n\nExample:\n```text\nclass Session(dict, SessionMixin):\n    pass\n```\n\nExample:\n```text\napp = Flask(__name__)\napp.session_interface = MySessionInterface()\n```\n\nExample:\n```text\nwith client.session_transaction() as session:\n    session['value'] = 42\n```\n\nExample:\n```text\nclass User(db.Model):\n\n    def __init__(self, username, remote_addr=None):\n        self.username = username\n        if remote_addr is None and has_request_context():\n            remote_addr = request.remote_addr\n        self.remote_addr = remote_addr\n```\n\nExample:\n```text\nclass User(db.Model):\n\n    def __init__(self, username, remote_addr=None):\n        self.username = username\n        if remote_addr is None and request:\n            remote_addr = request.remote_addr\n        self.remote_addr = remote_addr\n```\n\nExample:\n```text\nimport gevent\nfrom flask import copy_current_request_context\n\n@app.route('/')\ndef index():\n    @copy_current_request_context\n    def do_some_work():\n        # do some work here, it can access flask.request or\n        # flask.session like you would otherwise in the view function.\n        ...\n    gevent.spawn(do_some_work)\n    return 'Regular response'\n```\n\nExample:\n```text\ndef index():\n    return render_template('index.html', foo=42)\n```\n\nExample:\n```text\ndef index():\n    response = make_response(render_template('index.html', foo=42))\n    response.headers['X-Parachutes'] = 'parachutes are cool'\n    return response\n```\n\nExample:\n```text\nresponse = make_response(render_template('not_found.html'), 404)\n```\n\nExample:\n```text\nresponse = make_response(view_function())\nresponse.headers['X-Parachutes'] = 'parachutes are cool'\n```\n\nExample:\n```text\n@app.route('/')\ndef index():\n    @after_this_request\n    def add_header(response):\n        response.headers['X-Foo'] = 'Parachute'\n        return response\n    return 'Hello World!'\n```\n\nExample:\n```text\n@app.route(\"/uploads/<path:name>\")\ndef download_file(name):\n    return send_from_directory(\n        app.config['UPLOAD_FOLDER'], name, as_attachment=True\n    )\n```\n\nExample:\n```text\n<script>\n    const names = {{ names|tojson }};\n    renderChart(names, {{ axis_data|tojson }});\n</script>\n```\n\nExample:\n```text\nfrom flask.json.tag import JSONTag\n\nclass TagOrderedDict(JSONTag):\n    __slots__ = ('serializer',)\n    key = ' od'\n\n    def check(self, value):\n        return isinstance(value, OrderedDict)\n\n    def to_json(self, value):\n        return [[k, self.serializer.tag(v)] for k, v in iteritems(value)]\n\n    def to_python(self, value):\n        return OrderedDict(value)\n\napp.session_interface.serializer.register(TagOrderedDict, index=0)\n```\n\nExample:\n```text\n{% macro hello(name) %}Hello {{ name }}!{% endmacro %}\n```\n\nExample:\n```text\nhello = get_template_attribute('_cider.html', 'hello')\nreturn hello('World')\n```\n\nExample:\n```text\napp.config.from_pyfile('yourconfig.cfg')\n```\n\nExample:\n```text\nDEBUG = True\nSECRET_KEY = 'development key'\napp.config.from_object(__name__)\n```\n\nExample:\n```text\napp.config.from_envvar('YOURAPPLICATION_SETTINGS')\n```\n\nExample:\n```text\nexport YOURAPPLICATION_SETTINGS='/path/to/config/file'\n```\n\nExample:\n```text\napp.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])\n```\n\nExample:\n```text\napp.config.from_object('yourapplication.default_config')\nfrom yourapplication import default_config\napp.config.from_object(default_config)\n```\n\nExample:\n```text\nimport json\napp.config.from_file(\"config.json\", load=json.load)\n\nimport tomllib\napp.config.from_file(\"config.toml\", load=tomllib.load, text=False)\n```\n\nExample:\n```text\napp.config['IMAGE_STORE_TYPE'] = 'fs'\napp.config['IMAGE_STORE_PATH'] = '/var/app/images'\napp.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com'\nimage_store_config = app.config.get_namespace('IMAGE_STORE_')\n```\n\nExample:\n```text\n{\n    'type': 'fs',\n    'path': '/var/app/images',\n    'base_url': 'http://img.website.com'\n}\n```\n\nExample:\n```text\nfrom flask import stream_with_context, request, Response\n\n@app.get(\"/stream\")\ndef streamed_response():\n    @stream_with_context\n    def generate():\n        yield \"Hello \"\n        yield request.args[\"name\"]\n        yield \"!\"\n\n    return Response(generate())\n```\n\nExample:\n```text\nfrom flask import stream_with_context, request, Response\n\n@app.get(\"/stream\")\ndef streamed_response():\n    def generate():\n        yield \"Hello \"\n        yield request.args[\"name\"]\n        yield \"!\"\n\n    return Response(stream_with_context(generate()))\n```\n\nExample:\n```text\ndef log_template_renders(sender, template, context, **extra):\n    sender.logger.debug('Rendering template \"%s\" with context %s',\n                        template.name or 'string template',\n                        context)\n\nfrom flask import template_rendered\ntemplate_rendered.connect(log_template_renders, app)\n```\n\nExample:\n```text\ndef log_template_renders(sender, template, context, **extra):\n    sender.logger.debug('Rendering template \"%s\" with context %s',\n                        template.name or 'string template',\n                        context)\n\nfrom flask import before_render_template\nbefore_render_template.connect(log_template_renders, app)\n```\n\nExample:\n```text\ndef log_request(sender, **extra):\n    sender.logger.debug('Request context is set up')\n\nfrom flask import request_started\nrequest_started.connect(log_request, app)\n```\n\nExample:\n```text\ndef log_response(sender, response, **extra):\n    sender.logger.debug('Request context is about to close down. '\n                        'Response: %s', response)\n\nfrom flask import request_finished\nrequest_finished.connect(log_response, app)\n```\n\nExample:\n```text\nfrom flask import got_request_exception\n\ndef log_security_exception(sender, exception, **extra):\n    if not isinstance(exception, SecurityException):\n        return\n\n    security_logger.exception(\n        f\"SecurityException at {request.url!r}\",\n        exc_info=exception,\n    )\n\ngot_request_exception.connect(log_security_exception, app)\n```\n\nExample:\n```text\ndef close_db_connection(sender, **extra):\n    session.close()\n\nfrom flask import request_tearing_down\nrequest_tearing_down.connect(close_db_connection, app)\n```\n\nExample:\n```text\ndef close_db_connection(sender, **extra):\n    session.close()\n\nfrom flask import appcontext_tearing_down\nappcontext_tearing_down.connect(close_db_connection, app)\n```\n\nExample:\n```text\nfrom contextlib import contextmanager\nfrom flask import appcontext_pushed\n\n@contextmanager\ndef user_set(app, user):\n    def handler(sender, **kwargs):\n        g.user = user\n    with appcontext_pushed.connected_to(handler, app):\n        yield\n```\n\nExample:\n```text\ndef test_user_me(self):\n    with user_set(app, 'john'):\n        c = app.test_client()\n        resp = c.get('/users/me')\n        assert resp.data == 'username=john'\n```\n\nExample:\n```text\nrecorded = []\ndef record(sender, message, category, **extra):\n    recorded.append((message, category))\n\nfrom flask import message_flashed\nmessage_flashed.connect(record, app)\n```\n\nExample:\n```text\nclass Hello(View):\n    init_every_request = False\n\n    def dispatch_request(self, name):\n        return f\"Hello, {name}!\"\n\napp.add_url_rule(\n    \"/hello/<name>\", view_func=Hello.as_view(\"hello\")\n)\n```\n\nExample:\n```text\nclass CounterAPI(MethodView):\n    def get(self):\n        return str(session.get(\"counter\", 0))\n\n    def post(self):\n        session[\"counter\"] = session.get(\"counter\", 0) + 1\n        return redirect(url_for(\"counter\"))\n\napp.add_url_rule(\n    \"/counter\", view_func=CounterAPI.as_view(\"counter\")\n)\n```\n\nExample:\n```text\n@app.route('/')\ndef index():\n    pass\n\n@app.route('/<username>')\ndef show_user(username):\n    pass\n\n@app.route('/post/<int:post_id>')\ndef show_post(post_id):\n    pass\n```\n\nExample:\n```text\n@app.route('/users/', defaults={'page': 1})\n@app.route('/users/page/<int:page>')\ndef show_users(page):\n    pass\n```\n\nExample:\n```text\n@app.route('/region/', defaults={'id': 1})\n@app.route('/region/<int:id>', methods=['GET', 'POST'])\ndef region(id):\n   pass\n```\n\nExample:\n```text\ndef index():\n    if request.method == 'OPTIONS':\n        # custom options handling here\n        ...\n    return 'Hello World!'\nindex.provide_automatic_options = False\nindex.methods = ['GET', 'OPTIONS']\n\napp.add_url_rule('/', index)\n```\n\n<|endofdoc|>","metadata":{"transformedAt":"2026-08-18T15:17:33.128Z","totalSectionsIncluded":1,"totalCodeBlocksIncluded":73,"totalLines":638,"estimatedTokens":39622}}74