flasklet
A few nice things for Flask: typed configuration, flash messages with delivery types, convention-based blueprint discovery, route imports, and template rendering helpers.
Quick start
Install with uv add flasklet. Create these files:
myapp/
__init__.py
admin/
__init__.py
routes.py
templates/
index.html
components.html
partial.html
myapp/__init__.py:
from enum import StrEnum
from flask import Flask
from flasklet import config, init_template_helpers, register_blueprints
class Mode(StrEnum):
DEVELOPMENT = "development"
PRODUCTION = "production"
class Settings(config.Config, prefix="MYAPP_"):
secret_key: str = config.from_env()
mode: Mode = config.from_env(default=Mode.DEVELOPMENT)
def create_app() -> Flask:
app = Flask(__name__)
settings = config.load(Settings)
config.init_app(app, settings, flask_keys={"SECRET_KEY": "secret_key"})
init_template_helpers(app)
register_blueprints(app, auto_import_routes=True)
return app
myapp/admin/__init__.py:
from flask import Blueprint
bp = Blueprint("admin", __name__)
myapp/admin/routes.py:
from flask import Response, redirect, render_template, url_for
from flasklet import config, flash_message, parse_flashed_messages
from myapp import Settings
from . import bp
@bp.get("/")
def index() -> str:
return render_template(
"index.html",
mode=config.read_config(Settings).mode.value,
messages=parse_flashed_messages(),
)
@bp.post("/notice")
def notice() -> Response:
flash_message("Saved", type="toast", category="success")
return redirect(url_for("admin.index"))
myapp/templates/index.html:
{{ render_macro("components.html", "badge", value=mode) }}
{{ render_block("components.html", "notice", text="Welcome") }}
{{ render_partial("partial.html", text="Rendered separately") }}
{% for message in messages %}
<p data-type="{{ message.type }}" class="{{ message.category }}">{{ message.text }}</p>
{% endfor %}
<form action="{{ url_for('admin.notice') }}" method="post">
<button type="submit">Flash a message</button>
</form>
myapp/templates/components.html:
{% macro badge(value) %}<strong>{{ value }}</strong>{% endmacro %}
{% block notice %}<p>{{ text }}</p>{% endblock %}
myapp/templates/partial.html:
<aside>{{ text }}</aside>
Run MYAPP_SECRET_KEY=local-example-only uv run flask --app myapp:create_app run,
then open http://127.0.0.1:5000/.
Typed configuration
config.load(Settings) reads environment variables when called. A field's name
defaults to its uppercased attribute name, preceded by the class prefix. Pass a
name to from_env to override it. load(Settings, prefix=...) adds a prefix in
front of the class prefix.
Supported types are str, int, float, bool, Path, Enum subclasses,
Optional[T], list[T], and NewType wrappers. Enum variables match the
string representation of a member's value exactly. For example,
MYAPP_MODE=production selects Mode.PRODUCTION. An invalid value reports the
environment variable and allowed values. Booleans accept only true and
false. Lists are comma-separated; an empty variable gives an empty list.
For Optional[T], an empty variable gives None.
A field without a default is required. Use default_factory for values that
must be created per instance. Mutable list, dict, and set defaults are
deep-copied. Derived fields are computed once, in declaration order:
from pathlib import Path
class Storage(config.Config, prefix="MYAPP_"):
data_dir: Path | None = config.from_env(default=None)
base_dir: Path = config.derived(lambda s: (s.data_dir or Path.cwd()).resolve())
config.init_app stores the settings on the Flask app. flask_keys copies
selected attributes into Flask's own config, which is needed for values such as
SECRET_KEY. In an app context, config.read_config(Settings) returns the
registered instance. Outside an app context, it loads a new instance from the
current environment on every call.
Blueprint and route discovery
register_blueprints(app) scans subpackages of the app package for a module
attribute named bp. It registers each discovered blueprint on its parent
blueprint or on the app. A subpackage without bp and its children are skipped.
Call it during app creation, before handling requests. The same imported
blueprints can be registered on separate app instances.
Pass auto_import_routes=True to import modules next to each discovered blueprint
and in its routes/ directory before registration. This is opt-in because
importing a module runs its top-level code. The quick start uses this option.
import_routes(__file__, __name__) imports every Python module in the current
package directory and its routes/ directory, in sorted order. Route
decorators run as those modules are imported. It returns None. Use it in a
package's __init__.py when you want explicit route imports instead.
Flash messages
flash_message(text, type="toast", category="success") adds a delivery type to
Flask's ordinary flash category. Read messages with parse_flashed_messages();
each result has text, type, and category. Messages from Flask's own
flash() are returned with type="message". Use parse_flashed_messages()
when mixing the two functions.
Template helpers
init_template_helpers(app) registers render_block, render_macro,
render_macro_unsafe, and render_partial as Jinja globals. Call it in the
app factory before rendering templates. You can also register individual
functions with app.add_template_global.
render_partial renders a complete template. render_block renders a block
defined in the named template; it does not resolve a block that exists only in
a parent template, and the selected block cannot use super().
render_macro renders only the selected macro. Other top-level expressions in
the source template are not evaluated. Its keyword arguments serve two roles:
arguments with names declared by the macro are passed to it, and all arguments
are available as template context. A misspelled or unused keyword argument
has no effect, so check argument names when output is missing.
render_macro follows the app's Jinja autoescaping. render_macro_unsafe disables
autoescaping and returns an ordinary string. Use it only when the macro values
are trusted HTML. When calling it from a Jinja template, the result needs
|safe to avoid escaping the rendered HTML.
To include a file's source without Jinja processing, import
IncludeRawExtension from flasklet, register it with
app.jinja_env.add_extension(IncludeRawExtension), and use
{% include_raw "path/to/file" %} in a template.
Metadata
Release files for flasklet 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| flasklet-1.3.0.tar.gz | 13.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flasklet-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.5 kB
Release files / flasklet-1.3.0.tar.gz
| Download URL | flasklet-1.3.0.tar.gz |
|---|---|
| Size | 13.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a825a871619ac7241512ec91579b6492ae1b8f5f4bc51301ffc3e77cf1b1ff95
|
|
BLAKE2b-256 checksum How to use checksums |
c47b016366d97bc04e56bfa071377b487a56e9040b2e8ee4c5e59c1b05eb5a68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / flasklet-1.3.0-py3-none-any.whl
| Download URL | flasklet-1.3.0-py3-none-any.whl |
|---|---|
| Size | 17.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b733bd108c444a83ca78d7f3b8d67b01f847805fd2b5ec66c394f0864b8b3685
|
|
BLAKE2b-256 checksum How to use checksums |
d830401908e824cdec28579eca326174bff9928ef4d1186e77ddaa4bb91e358f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|