Flask 3.1.3 is a security fix release. It also includes a small set of follow-up changes around docs, context handling, and request/response behavior that are worth noting for upgraders.
What's new
- Adds support for using
@app.template_filterwithout parentheses. The existing forms still work too, including@app.template_filter(),@app.template_filter(name="..."), and@app.template_filter("..."). The same decorator pattern is intended to carry over totemplate_globalandtemplate_testlater. (#5736) - Merges the separate request and app context machinery into a single internal context model. From a user point of view, the usual APIs still exist:
teardown_request,teardown_appcontext,app.app_context,app.test_request_context, and the global proxies all continue to work in the same situations. (#5812) - Passes the
AppContextthrough Flask’s request dispatch methods instead of having each method reach back through context proxies. This change covers methods likedispatch_request,full_dispatch_request,process_response, anddo_teardown_request, and keeps compatibility during a deprecation period for older subclass signatures. (#5818) - Documents using gevent for async support. The new guidance includes examples with asyncio and libuv, and removes mentions of eventlet. (#5900)
Breaking changes
- Flask 3.1.3 itself is explicitly intended not to introduce breaking behavior beyond the security fix, but the internal context merge and dispatch-signature work does affect subclassing. If you override the affected Flask methods, the second parameter now needs to be
ctxor a compatible annotation, and old signatures are detected during subclass initialization. (#5812, #5818) redirect()now defaults to HTTP 303 instead of 302. That means redirects will now resolve to a GET in the common POST-redirect-GET flow. (#5898)
Fixes
- Session access is now recorded even for operations that only touch keys, like
inandlen. (#5924) provide_automatic_optionsnow enablesOPTIONScorrectly when it is set, instead of only allowing it to be disabled. (#5917)select_jinja_autoescapehas the correct type annotation for filenames that may beNone. (#5808)- Flask now aborts if the instance folder cannot be created, instead of ignoring a
PermissionErrorsilently. (#5903) request.jsondocumentation now clearly distinguishes400 Bad Requestfor invalid JSON from415 Unsupported Media Typefor a missing or incorrectContent-Typeheader. (#5827)
Other notable changes
should_ignore_erroris deprecated. (#5899)- The required
flit_coreversion was raised to 3.11. (#5865) - GitHub Actions artifact handling was hardened by switching to
artifact-idand disabling persisted checkout credentials in the publish workflow. (#5795)
Contributors
@davidism @adityasah104 @kadai0308 @subhajitsaha01 @marcows @GrantBirki @cclauss @hynek