PyBladePyBlade

Framework integration

How to connect PyBlade to Django, Flask, FastAPI and the other Python web frameworks.

PyBlade is a template engine, so it needs one small connection to your web framework: something that says "render this template with PyBlade". How that connection is made depends on the framework.

FrameworkHow it is connectedSupport
DjangoA template backend in settings.pyFull
Flaskrender from pyblade.flaskTemplates
FastAPIrender from pyblade.fastapiTemplates
Starletterender from pyblade.starletteTemplates
Quartrender from pyblade.quartTemplates
Litestarrender from pyblade.litestarTemplates
Sanicrender from pyblade.sanicTemplates

Django is the fully supported framework

Today, Django is the only framework where every PyBlade feature is available. In the other frameworks PyBlade renders your templates, but some directives depend on Django and live components are not available yet. See what is different outside Django.

Django

Django is the only framework that needs settings to be changed. Everything below goes in settings.py and urls.py. If you started your project with pyblade init, all of it is already done.

The template backend

Django renders templates through backends. Add PyBlade's, and put it before Django's own so that PyBlade gets the first chance to find a template:

settings.py
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
    {
        "BACKEND": "pyblade.django.PyBladeEngine",
        "NAME": "pyblade",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

Keeping Django's backend as the first entry means the Django admin, and any third-party app that ships Django templates, keep working. Django asks each backend in turn until one has the template.

What this gives you:

  • django.shortcuts.render(), TemplateResponse and class-based views such as TemplateView all render through PyBlade. There is nothing PyBlade-specific to call.
  • The context_processors you list run for PyBlade templates too, and request, csrf_token and csrf_input are always in the context.
  • With APP_DIRS: True, PyBlade looks for a templates folder in each installed app, the way Django does. The folder's name comes from paths.templates in pyblade.toml.
views.py
from django.shortcuts import render


def home(request):
    return render(request, "home", {"name": "Ada"})

Templates are named without their .html extension: render(request, "home") finds templates/home.html. See creating your first project for how templates are organized.

Live components

Live components need two more things.

Add the app to INSTALLED_APPS:

settings.py
INSTALLED_APPS = [
    # ...
    "pyblade.live",
]

Include its URLs. They are the endpoints the browser talks to (actions, uploads, previews and PyBlade's own script and styles):

urls.py
from django.urls import include, path

urlpatterns = [
    # ...
    path("", include("pyblade.live.urls")),
]

Then put @pbstyles and @pbscripts in your layout, as described in the live components quickstart.

Other settings PyBlade reads

PyBlade doesn't ask you for extra settings, but it does use some Django ones:

SettingUsed for
SECRET_KEYSigning the state of live components. See Security
DEBUGShowing PyBlade's error page, control @debug behavior.
STATIC_URL, MEDIA_URLThe @static, @get_static_prefix and @get_media_prefix directives
LANGUAGES, the active language@trans, @blocktrans and language lists
MIDDLEWARECsrfViewMiddleware protects your forms and the live endpoints
The CACHES defaultCounting requests for the live rate limits

PyBlade's own configuration in settings.py

PyBlade's options normally live in pyblade.toml, but a Django project can also write them in a PYBLADE dictionary, and what it says wins over the file:

settings.py
PYBLADE = {
    "live_components": {
        "throttle": {"actions": "60/minute"},
    },
    "i18n": {"locale": "fr"},
}

This is useful to change an option per environment (settings/production.py) or to compute one from the environment. The page on configuration explains the order in which everything is read.

Flask

Flask needs no changes to its configuration. Import render from pyblade.flask and use it where you would use render_template:

app.py
from flask import Flask
from pyblade.flask import render

app = Flask(__name__)


@app.route("/")
def home():
    return render("home", name="Ada")

render_template is provided too, under the name Flask developers already know, so you can switch an existing project one import at a time:

from pyblade.flask import render_template
  • Templates are looked for in the folder Flask already knows: the application's template_folder (templates by default).
  • Each Flask application gets an engine of its own, so applications that run in the same process, each with their own templates, don't mix.
  • To use another folder, call configure once when your application starts:
from pyblade.flask import configure

configure("/path/to/templates")

FastAPI, Starlette, Litestar and Sanic

These frameworks work the same way. Import render from the module named after your framework and hand it the request first:

main.py
from fastapi import FastAPI, Request
from pyblade.fastapi import render

app = FastAPI()


@app.get("/")
def home(request: Request):
    return render(request, "home", name="Ada")

The request is added to the template's context as request, and render returns an HTML response from your framework.

These frameworks have no template folder of their own to ask, so PyBlade uses the paths.templates setting of your pyblade.toml (templates by default). To use another folder, say so once when the application starts:

from pyblade.fastapi import configure

configure("/path/to/templates")

Quart

Quart follows Flask, except that its render is a coroutine, as Quart's own render_template is:

app.py
from quart import Quart
from pyblade.quart import render

app = Quart(__name__)


@app.route("/")
async def home():
    return await render("home", name="Ada")

What is different outside Django

PyBlade's core (the syntax, escaping, the expression sandbox, components, inheritance, loops, conditions and filters) is the same in every framework. What differs is what needs the framework's help.

FeatureDjangoOther frameworks
Directives, components, layouts, inheritanceYesYes
{{ }} escaping and the expression sandboxYesYes
Live componentsYesNot available yet
@csrfYes, with the token Django createsProvides no token: a token must be in the context as csrf_token
@urlUses Django's URL resolverRenders nothing
@staticUses STATIC_URLWrites /static/<path>
@get_static_prefix, @get_media_prefixUse STATIC_URL, MEDIA_URLWrite /static/ and /media/
@authReads request.userReads a user you pass in the context, or request.user if the request has one
@trans and language listsDjango's translation systemPyBlade's own translations, from the locale folder
Error page in DEBUG modeDjango's DEBUGFlask's debug mode, or a DEBUG=true environment variable for FastAPI

Not tested outside Django

The behaviors in the right-hand column describe what PyBlade is designed to do outside Django. The directives that depend on the framework (@csrf, @auth, @static, @trans...) have only been tested with Django so far, so check them in your own project before relying on them.

Set the framework in pyblade.toml

A few of the behaviors above depend on knowing which framework serves the project, such as @static and translations. Make sure stack.framework is set in pyblade.toml (pyblade init does it for you), or PyBlade can't tell Django from the rest.

Support for the other frameworks is growing. If a directive you need doesn't work outside Django, or you would like another framework to be supported, tell us on the feedback platform.

On this page