Skip to content

API Reference

This page contains the complete API reference for Starlette Templates.

TemplateRouter

TemplateRouter(
    *,
    directory: PathLike | None = None,
    extensions: list[str] | None = None,
    index_files: list[str] | None = None,
    check_dir: bool = True,
    follow_symlink: bool = False,
    cache_max_age: int = 3600,
    gzip_min_size: int = 500,
    context_processors: list[
        Callable[[Request], Awaitable[dict[str, Any]]]
        | Route
    ]
    | None = None,
    jinja_env: Environment | None = None,
    debug: bool = False,
    error_handler: Callable[
        [Request, Exception], Awaitable[Response]
    ]
    | None = None,
)

ASGI app for routing HTTP requests to Jinja2 templates with automatic resolution.

Routes incoming requests to templates with Jinja2 rendering, HTTP caching, gzip compression, and automatic file resolution (extension fallbacks, index files).

Architecture with two modes of operation: The system supports two distinct operational modes. When initialized with a directory parameter, it uses filesystem lookups to find templates through direct file access with stat and permissions checking, which is useful when templates are in a known directory. Alternatively, when initialized without a directory parameter (directory=None), it uses jinja_env loaders such as PackageLoader or FileSystemLoader, allowing templates to be served from locations defined in JinjaMiddleware, providing a single source of truth for template locations without configuration duplication.

Flow
  1. JinjaMiddleware defines template loaders
  2. Mount TemplateRouter() without directory parameter
  3. Request comes in: /forms
  4. TemplateRouter.get_response() called
  5. Delegates to render_template_from_loaders()
  6. Gets jinja_env from request.state
  7. Tries candidates: forms.html, forms.htm, etc.
  8. Finds template using jinja_env.loader.get_source()
  9. Renders template with context {"request": request}
  10. Returns ContentResponse with caching headers

Context processors are callables that accept a Request and return a dict of additional context variables to be merged into the template context.

Parameters:

  • directory (PathLike | None, default: None ) –

    Optional path to templates directory (None = use jinja_env loaders)

  • extensions (list[str] | None, default: None ) –

    List of allowed file extensions (default: [".html", ".htm", ".jinja", ".jinja2"])

  • index_files (list[str] | None, default: None ) –

    List of index filenames to search for (default: ["index.html", "index.htm"])

  • check_dir (bool, default: True ) –

    Whether to check if directory exists on init

  • follow_symlink (bool, default: False ) –

    Whether to follow symlinks in directory

  • cache_max_age (int, default: 3600 ) –

    Max age for HTTP caching (in seconds)

  • gzip_min_size (int, default: 500 ) –

    Minimum size (in bytes) to apply gzip compression

  • context_processors (list[Callable[[Request], Awaitable[dict[str, Any]]] | Route] | None, default: None ) –

    List of async callables to add to template context

  • jinja_env (Environment | None, default: None ) –

    Optional Jinja2 Environment (falls back to request.state.jinja_env)

  • debug (bool, default: False ) –

    Whether to enable debug mode (shows detailed error pages)

  • error_handler (Callable[[Request, Exception], Awaitable[Response]] | None, default: None ) –

    Callable to handle exceptions and return custom responses (uses built-in handler if None)

Example
app = Starlette(
    routes=[
        # Override specific paths, like / which would map to index.html
        Route("/", homepage, name="home"),
        # Catch-all for templates
        Mount("/", TemplateRouter()),
    ],
    middleware=[
        Middleware(
            JinjaMiddleware,
            template_loaders=[PackageLoader("myapp", "templates")]
        )
    ]
)

StaticFiles

StaticFiles(
    *,
    directories: List[PathLike] | None = None,
    packages: list[str | tuple[str, str]] | None = None,
    html: bool = False,
    check_dir: bool = True,
    follow_symlink: bool = False,
)

Enhanced StaticFiles with gzip compression, caching, and multi-directory support.

Features: - Automatic gzip handling for .gz files with proper Content-Encoding headers - Strong HTTP caching (ETag, Cache-Control, Last-Modified) - Multi-directory fallback support (searches directories in priority order)

When a .gz file is requested directly, this class automatically: 1. Strips the .gz extension from the Content-Type detection 2. Sets Content-Encoding: gzip header 3. Adds Vary: Accept-Encoding header 4. Adds strong caching headers (Cache-Control: public, max-age=31536000, immutable)

When multiple directories are provided, files are searched in priority order, allowing application static files to override framework static files.

Parameters:

  • directories (List[PathLike] | None, default: None ) –

    Directory paths to search (in priority order)

  • packages (list[str | tuple[str, str]] | None, default: None ) –

    Package resources to serve

  • html (bool, default: False ) –

    Enable HTML mode

  • check_dir (bool, default: True ) –

    Whether to check if directories exist on initialization

  • follow_symlink (bool, default: False ) –

    Whether to follow symbolic links

Example with single directory
static = StaticFiles(directories=["static"])

Example with multiple directories (priority-based override):

static = StaticFiles(
    directories=[Path("app/static"), Path("framework/static")],
    packages=[("myapp", "static")],
)

Example serving pre-compressed files
<link rel="stylesheet" href="{{ url_for('static', path='vendor/bootstrap.css.gz') }}">

The browser receives: - Content-Type: text/css - Content-Encoding: gzip - Cache-Control: public, max-age=31536000, immutable - And automatically decompresses the content

TemplateResponse

TemplateResponse(
    template_name: str,
    context: dict[str, Any] | None = None,
    status_code: int = 200,
    headers: Mapping[str, str] | None = None,
    media_type: str | None = None,
    background: Any = None,
)

HTMLResponse subclass that renders Jinja2 templates.

This class provides a convenient way to render Jinja2 templates from route handlers without manually accessing the Jinja2 environment.

The template will have access to standard context variables:

  • request: The Starlette Request object
  • url_for: Function to generate URLs for named routes
  • absurl: Function to generate absolute URLs
  • base_url: The base URL of the application
  • url: Function to build full URLs from paths
  • jsonify: Function to serialize data to JSON for embedding in HTML
  • Plus any custom context variables provided

Parameters:

  • template_name (str) –

    The name of the Jinja2 template to render

  • request

    The Starlette Request object (required for accessing app's Jinja2 env)

  • context (dict[str, Any] | None, default: None ) –

    The context data to pass to the template

  • status_code (int, default: 200 ) –

    The HTTP status code for the response

  • headers (Mapping[str, str] | None, default: None ) –

    Additional headers for the response

  • media_type (str | None, default: None ) –

    The media type for the response

  • background (Any, default: None ) –

    A background task to run after the response is sent

Example
from starlette_templates import Application, TemplateResponse, route, model_from_request
from starlette.requests import Request
from pydantic import BaseModel

class UserModel(BaseModel):
    id: int
    name: str

@route("/users/{user_id}")
async def user_profile(request: Request) -> TemplateResponse:
    user  = model_from_request(request, UserModel)

    return TemplateResponse(
        "user_profile.html",
        context={"user": user},
    )

app = Application(
    routes=[user_profile],
    package_name="myapp",
)

JinjaMiddleware

JinjaMiddleware(
    app: ASGIApp,
    *,
    state_key: str = "jinja_env",
    include_websocket: bool = True,
    template_loaders: list[
        Union[PackageLoader, FileSystemLoader]
    ]
    | None = None,
    include_default_loader: bool = True,
    extra_components: ModuleType
    | type[ComponentModel]
    | Sequence[ModuleType | type[ComponentModel]]
    | None = None,
    jinja_globals: dict[str, Any] | None = None,
    jinja_filters: dict[str, Callable] | None = None,
)

Middleware to inject Jinja2 environment into request state.

This middleware creates a Jinja2 environment with the provided template loaders and makes it available in the request scope under a specified key, by default "jinja_env". This allows downstream components to access the Jinja2 environment for template rendering.

Parameters:

  • app (ASGIApp) –

    The ASGI application

  • state_key (str, default: 'jinja_env' ) –

    The key under which to store the Jinja2 environment in request state

  • include_websocket (bool, default: True ) –

    Whether to include WebSocket connections for Jinja2 env injection

  • template_loaders (list[Union[PackageLoader, FileSystemLoader]] | None, default: None ) –

    List of Jinja2 template loaders to configure the environment.

  • include_default_loader (bool, default: True ) –

    Include the default PackageLoader for "starlette_templates"

  • component_modules

    Optional module, ComponentModel class, or sequence of either to auto-register components from. Can be a single module, a single ComponentModel class, or a list containing any mix of modules and ComponentModel classes.

Example
from starlette.applications import Starlette
from starlette_templates.middleware import JinjaMiddleware
from jinja2 import PackageLoader, FileSystemLoader

from myapp import custom_components  # A module with custom components
from myapp.components import CustomButton, CustomCard  # Individual component classes

app = Starlette()
app.add_middleware(
    JinjaMiddleware,
    template_loaders=[
        PackageLoader("myapp", "templates"),
        FileSystemLoader("custom/templates"),
    ],
    include_default_loader=True,
    # Can pass a single module, a single component, or a list of either
    component_modules=[custom_components, CustomButton, CustomCard],
)

FormModel

FormModel(**data)

Base class for form models with rendering capabilities.

Attributes:

  • model_config

    Configuration for form rendering and behavior

Example

Define a form model by inheriting from FormModel and using form field helpers:

import datetime
from starlette_templates.forms import FormModel, SelectField, DateField, SubmitButtonField

class Filters(FormModel):
    storefront: str = SelectField(
        default="ww",
        choices={"ww": "Worldwide", "us": "United States"},
        label="Storefront",
    )
    start_date: datetime.date = DateField(
        default_factory=lambda: datetime.date.today(),
        label="Start Date",
    )
    submit: str = SubmitButtonField(text="Submit")

Add forms to a specific template using TemplateResponse

async def overview(request: Request) -> TemplateResponse:
    form = await Filters.from_request(request)
    return TemplateResponse("overview.html", {"form": form})

app = Starlette(routes=[
    Route("/overview", overview, methods=["GET", "POST"], name="overview")
])

Add forms to all templates using context_processors parameter of TemplateRouter

async def form_context_processor(request: Request) -> dict:
    form = await Filters.from_request(request)
    return {"form": form}

app = Starlette(
    routes=[
        Mount("/", TemplateRouter(
            context_processors=[form_context_processor],
        )),
    ],
    middleware=[Middleware(Jinja2TemplatesMiddleware)],
)

Or assign forms to specific routes using Route in context_processors

app = Starlette(
    routes=[
        Route(
            "/",
            TemplateRouter(
                context_processors=[
                    # Only add form to /search route templates
                    Route("/search", form_context_processor)
                ],
            ),
        ),
    ],
    middleware=[Middleware(Jinja2TemplatesMiddleware)],
)

Methods:

  • from_request

    Create form instance from request data.

  • is_valid

    Check if form has no validation errors. If request is provided,

  • render

    Render a specific field in HTML. This is a Jinja2 template method.

  • has_errors

    Check if form has validation errors. If name is provided, checks for errors on that specific field.

  • get_field_error

    Get validation error message for a specific field, if any.

  • get_error_banner_text

    Get the error banner text from form config. This is text that can be displayed

  • model_dump

    Override model_dump to exclude fields marked with exclude_from_dump.

  • __call__

    Render the entire form. Alias for render_form().

from_request async classmethod

from_request(
    request: Request, raise_on_error: bool = True
) -> FormModel

Create form instance from request data.

This class method parses data from the request (path params, query params, form data, and JSON body) and validates it against the form model and returns an instance of the form model. If validation errors occur, they are either raised as ValidationError or captured in the instance based on the raise_on_error flag.

If a field with the same name appears in multiple sources, the precedence is as follows: path params < query params < form data < JSON body. For example, if a field is present in both query params and form data, the value from form data will be used.

Use the .is_valid() method on the returned instance to check if the form data is valid when raise_on_error is False.

Parameters:

  • request (Request) –

    Starlette Request object

  • raise_on_error (bool, default: True ) –

    If True, raises ValidationError. If False, captures errors in instance.

Returns:

  • FormModel

    FormModel instance (with errors if raise_on_error=False)

is_valid

is_valid(request: Request | None = None) -> bool

Check if form has no validation errors. If request is provided, checks for both HTTP method and field errors to determine validity.

If request is provided, the form is only considered valid if the request method is the same as the form's configured method (default: POST) and there are no field errors. This means is_valid() will return False for GET requests even if there are no field errors and will only return True for requests with the correct method and no field errors, which is the typical behavior for form submissions.

Parameters:

  • request (Request | None, default: None ) –

    Starlette Request object (optional)

Returns:

  • bool

    True if form is valid, False otherwise

Example
async def search_page(request: Request):
    form = await SearchForm.from_request(request)
    if form.is_valid(request):
        # Process valid form submission
        ...
    return TemplateResponse("search.html", {"form": form})

render async

render(
    ctx: Context,
    field_name: str,
    request: Request | None = None,
) -> Markup

Render a specific field in HTML. This is a Jinja2 template method.

This calls the component's render method with appropriate parameters defined in the form.

If the request parameter is not provided, it will attempt to get it from the template context. If the request is still not found, an error will be raised.

Parameters:

  • ctx (Context) –

    Jinja2 context

  • field_name (str) –

    Name of the field to render

  • request (Request | None, default: None ) –

    Starlette request object

Returns:

  • Markup

    Markup of the rendered component HTML

Example

In a Jinja2 templates, use sync or async to render the field:

{{ form.render('start_date', request) }}
{{ await form.render('start_date', request) }}

You can also omit the request parameter if the template context has a request variable:

{{ form.render('start_date') }}

Raises:

  • ValueError

    If the request object is not provided or found in context

  • ValueError

    If the field name is not found in the form

  • ValueError

    If the field does not have a component_cls defined

has_errors

has_errors(name: str | None = None) -> bool

Check if form has validation errors. If name is provided, checks for errors on that specific field.

Parameters:

  • name (str | None, default: None ) –

    Name of the field to check for errors (optional)

Returns:

  • bool

    True if there are validation errors, False otherwise

Example
if form.has_errors():
    print("Form has validation errors")

if form.has_errors('email'):
    print("Email field has a validation error")

You can also use this in Jinja2 templates:

{% if form.has_errors() %}
    <div class="error-banner">{{ form.get_error_banner_text() }}</div>
{% endif %}

{% if form.has_errors('email') %}
    <div class="field-error">{{ form.get_field_error('email') }}</div>
{% endif %}

get_field_error

get_field_error(
    name: str, default: str | None = None
) -> str | None

Get validation error message for a specific field, if any.

Parameters:

  • name (str) –

    Name of the field

  • default (str | None, default: None ) –

    Default value to return if no error exists for the field

Returns:

  • str | None

    The error message for the field, or the default value if no error exists

Example
error_message = form.get_field_error('email', default='No error')

get_error_banner_text

get_error_banner_text() -> str

Get the error banner text from form config. This is text that can be displayed at the top of the form when there are validation errors.

model_dump

model_dump(**kwargs) -> dict[str, Any]

Override model_dump to exclude fields marked with exclude_from_dump.

__call__ async

__call__(
    ctx: Context,
    request: Request | None = None,
    *,
    id: str | None = None,
    action: str | None = None,
    method: str | None = None,
    enctype: str | None = None,
    classes: list[str] | None = None,
    novalidate: bool = False,
) -> Markup

Render the entire form. Alias for render_form().

Example
{{ form() }}
{{ form(action='/submit', classes=['my-form'], enctype='multipart/form-data') }}

TextField

TextField(
    default: Any = PydanticUndefined,
    *,
    min_length: int | None = None,
    max_length: int | None = None,
    regex: str | None = None,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = PydanticUndefined,
    description: str = PydanticUndefined,
    required: bool = False,
    hidden: bool = False,
    disabled: bool = False,
    readonly: bool = False,
    col_class: str | None = None,
    **kwargs: Any,
) -> Any

Create a string form field with validation and formatting options.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • min_length (int | None, default: None ) –

    Minimum length validation

  • max_length (int | None, default: None ) –

    Maximum length validation

  • regex (str | None, default: None ) –

    Regular expression pattern for validation

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: PydanticUndefined ) –

    Placeholder text for input

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • hidden (bool, default: False ) –

    Whether field is hidden

  • disabled (bool, default: False ) –

    Whether field is disabled

  • readonly (bool, default: False ) –

    Whether field is readonly

  • col_class (str | None, default: None ) –

    Bootstrap column class for horizontal layout (e.g., "col-md-4")

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for string validation

TextAreaField

TextAreaField(
    default: Any = PydanticUndefined,
    *,
    min_length: int | None = None,
    max_length: int | None = None,
    rows: int = 3,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = PydanticUndefined,
    description: str = PydanticUndefined,
    required: bool = False,
    disabled: bool = False,
    readonly: bool = False,
    **kwargs: Any,
) -> Any

Create a textarea form field for multi-line text input.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • min_length (int | None, default: None ) –

    Minimum length validation

  • max_length (int | None, default: None ) –

    Maximum length validation

  • rows (int, default: 3 ) –

    Number of rows for textarea

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: PydanticUndefined ) –

    Placeholder text for textarea

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • disabled (bool, default: False ) –

    Whether field is disabled

  • readonly (bool, default: False ) –

    Whether field is readonly

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for textarea input

EmailField

EmailField(
    default: Any = PydanticUndefined,
    *,
    max_length: int | None = None,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = PydanticUndefined,
    description: str = PydanticUndefined,
    required: bool = False,
    hidden: bool = False,
    disabled: bool = False,
    readonly: bool = False,
    **kwargs: Any,
) -> Any

Create an email form field with email validation.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • max_length (int | None, default: None ) –

    Maximum length validation

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: PydanticUndefined ) –

    Placeholder text for input

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • hidden (bool, default: False ) –

    Whether field is hidden

  • disabled (bool, default: False ) –

    Whether field is disabled

  • readonly (bool, default: False ) –

    Whether field is readonly

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for email validation

IntegerField

IntegerField(
    default: Any = PydanticUndefined,
    *,
    gt: int | None = None,
    ge: int | None = None,
    lt: int | None = None,
    le: int | None = None,
    multiple_of: int | None = None,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = PydanticUndefined,
    description: str = PydanticUndefined,
    required: bool = False,
    hidden: bool = False,
    disabled: bool = False,
    readonly: bool = False,
    **kwargs: Any,
) -> Any

Create an integer form field with numeric validation options.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • gt (int | None, default: None ) –

    Greater than validation

  • ge (int | None, default: None ) –

    Greater than or equal validation

  • lt (int | None, default: None ) –

    Less than validation

  • le (int | None, default: None ) –

    Less than or equal validation

  • multiple_of (int | None, default: None ) –

    Multiple of validation

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: PydanticUndefined ) –

    Placeholder text for input

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • hidden (bool, default: False ) –

    Whether field is hidden

  • disabled (bool, default: False ) –

    Whether field is disabled

  • readonly (bool, default: False ) –

    Whether field is readonly

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for integer validation

FloatField

FloatField(
    default: Any = PydanticUndefined,
    *,
    gt: float | None = None,
    ge: float | None = None,
    lt: float | None = None,
    le: float | None = None,
    multiple_of: float | None = None,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = PydanticUndefined,
    description: str = PydanticUndefined,
    required: bool = False,
    hidden: bool = False,
    disabled: bool = False,
    readonly: bool = False,
    **kwargs: Any,
) -> Any

Create a float form field with numeric validation options.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • gt (float | None, default: None ) –

    Greater than validation

  • ge (float | None, default: None ) –

    Greater than or equal validation

  • lt (float | None, default: None ) –

    Less than validation

  • le (float | None, default: None ) –

    Less than or equal validation

  • multiple_of (float | None, default: None ) –

    Multiple of validation

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: PydanticUndefined ) –

    Placeholder text for input

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • hidden (bool, default: False ) –

    Whether field is hidden

  • disabled (bool, default: False ) –

    Whether field is disabled

  • readonly (bool, default: False ) –

    Whether field is readonly

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for float validation

CheckboxField

CheckboxField(
    default: Any = PydanticUndefined,
    *,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    description: str = PydanticUndefined,
    value: str = "1",
    required: bool = False,
    disabled: bool = False,
    inline: bool = False,
    **kwargs: Any,
) -> Any

Create a checkbox form field for boolean input.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field (True/False)

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • description (str, default: PydanticUndefined ) –

    Field description

  • value (str, default: '1' ) –

    Value submitted when checkbox is checked

  • required (bool, default: False ) –

    Whether field is required

  • disabled (bool, default: False ) –

    Whether field is disabled

  • inline (bool, default: False ) –

    Whether to display inline

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for checkbox input

SelectField

SelectField(
    default: Any = PydanticUndefined,
    default_factory: Callable[[], Any]
    | None = PydanticUndefined,
    *,
    choices: Dict[Any, str]
    | List[Any]
    | List[Choice]
    | None = None,
    choices_factory: Callable[
        [], Dict[Any, str] | List[Any] | List[Choice]
    ]
    | None = None,
    multiple: bool = False,
    size: int | None = None,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = PydanticUndefined,
    required: bool = False,
    description: str = PydanticUndefined,
    disabled: bool = False,
    search_enabled: bool = True,
    search_placeholder: str = "Type to search",
    remove_button: bool = True,
    max_item_count: int | None = None,
    col_class: str | None = None,
    **kwargs: Any,
) -> Any

Create a select form field with options.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • choices (Dict[Any, str] | List[Any] | List[Choice] | None, default: None ) –

    Dict of {value: label}, list of values where value=label, or list of Choice objects. Order is preserved in all formats.

  • choices_factory (Callable[[], Dict[Any, str] | List[Any] | List[Choice]] | None, default: None ) –

    Callable that returns a dict, list, or list of Choice objects

  • multiple (bool, default: False ) –

    Whether multiple selections are allowed (uses ChoicesSelect when True)

  • size (int | None, default: None ) –

    Number of visible options (for Select component)

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: PydanticUndefined ) –

    Placeholder text (for ChoicesSelect)

  • required (bool, default: False ) –

    Whether field is required

  • description (str, default: PydanticUndefined ) –

    Field description

  • hidden

    Whether field is hidden

  • disabled (bool, default: False ) –

    Whether field is disabled

  • search_enabled (bool, default: True ) –

    Enable search functionality (for ChoicesSelect)

  • search_placeholder (str, default: 'Type to search' ) –

    Search placeholder text (for ChoicesSelect)

  • remove_button (bool, default: True ) –

    Show remove button for selected items (for ChoicesSelect)

  • max_item_count (int | None, default: None ) –

    Max items that can be selected (for ChoicesSelect with multiple)

  • col_class (str | None, default: None ) –

    Bootstrap column class for horizontal layout (e.g., "col-md-4")

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for select input

Example

Single select with dict choices (different value and label)

status = SelectField(
    choices={"active": "Active", "inactive": "Inactive", "pending": "Pending"},
    label="Status"
)

Single select with list choices (same value and label)

fruits = SelectField(
    choices=["Apple", "Orange", "Banana"],
    label="Fruit"
)

Single select with Choice objects

country = SelectField(
    choices=[
        Choice(value="us", label="United States"),
        Choice(value="ca", label="Canada"),
        Choice(value="uk", label="United Kingdom"),
    ],
    label="Country"
)

Multiple select (uses ChoicesSelect component)

interests = SelectField(
    choices={"sports": "Sports", "music": "Music", "reading": "Reading"},
    multiple=True,
    label="Interests"
)

Dynamic choices using a factory function

def get_country_choices():
    return {"us": "United States", "uk": "United Kingdom", "ca": "Canada"}

country = SelectField(
    choices_factory=get_country_choices,
    label="Country"
)

DateField

DateField(
    default: Any = PydanticUndefined,
    default_factory: Callable[[], Any]
    | None = PydanticUndefined,
    *,
    min: Any = PydanticUndefined,
    max: Any = PydanticUndefined,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    placeholder: str = "Select date",
    description: str = PydanticUndefined,
    required: bool = False,
    disabled: bool = False,
    mode: str = "single",
    enable_time: bool = False,
    time_24hr: bool = True,
    date_format: str = "Y-m-d",
    inline: bool = False,
    col_class: str | None = None,
    **kwargs: Any,
) -> Any

Create a date form field with Flatpickr date picker.

This field renders using the Flatpickr date picker component with advanced date selection features.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field (can be date, datetime, or string)

  • default_factory (Callable[[], Any] | None, default: PydanticUndefined ) –

    Factory function to generate default value

  • min (Any, default: PydanticUndefined ) –

    Minimum allowed date (date, datetime, or ISO string)

  • max (Any, default: PydanticUndefined ) –

    Maximum allowed date (date, datetime, or ISO string)

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • placeholder (str, default: 'Select date' ) –

    Placeholder text for input

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • hidden

    Whether field is hidden

  • disabled (bool, default: False ) –

    Whether field is disabled

  • mode (str, default: 'single' ) –

    Selection mode: "single", "multiple", or "range"

  • enable_time (bool, default: False ) –

    Enable time picker

  • time_24hr (bool, default: True ) –

    Use 24-hour time format

  • date_format (str, default: 'Y-m-d' ) –

    Date format string (Flatpickr format)

  • inline (bool, default: False ) –

    Display calendar inline

  • col_class (str | None, default: None ) –

    Bootstrap column class for horizontal layout (e.g., "col-md-4")

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for date input

Example

Basic date field

birth_date = DateField(label="Birth Date", required=True)

Date field with range constraints

event_date = DateField(
    label="Event Date",
    min="2024-01-01",
    max="2024-12-31"
)

Date field with default value

from datetime import date
appointment_date = DateField(
    label="Appointment Date",
    default=date.today(),
    required=True
)

Date range picker

date_range = DateField(
    label="Date Range",
    mode="range"
)

Date and time picker

appointment = DateField(
    label="Appointment",
    enable_time=True,
    date_format="Y-m-d H:i"
)

HiddenField

HiddenField(
    default: Any = PydanticUndefined,
    *,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    description: str = PydanticUndefined,
    **kwargs: Any,
) -> Any

Create a hidden form field for passing data without user interaction.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • title (str, default: PydanticUndefined ) –

    Field title

  • description (str, default: PydanticUndefined ) –

    Field description

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for hidden input

Example

Basic hidden field

csrf_token = HiddenField(default="abc123")

Hidden field with custom name

user_id = HiddenField(default=42, name="user_id")

Hidden field that excludes from validation

session_key = HiddenField(
    default="session_xyz",
    exclude_from_validation=True
)

SubmitButtonField

SubmitButtonField(
    text: str = "Submit",
    *,
    button_type: str = "submit",
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    classes: list[str] | None = None,
    disabled: bool = False,
    form: Any = PydanticUndefined,
    formaction: Any = PydanticUndefined,
    formenctype: Any = PydanticUndefined,
    formmethod: Any = PydanticUndefined,
    formnovalidate: bool = False,
    formtarget: Any = PydanticUndefined,
    col_class: str | None = None,
    **kwargs: Any,
) -> Any

Create a submit button form field with customization options.

Parameters:

  • text (str, default: 'Submit' ) –

    Button text/label

  • button_type (str, default: 'submit' ) –

    Button type (submit, button, reset)

  • name (Any, default: PydanticUndefined ) –

    Button name attribute

  • id (Any, default: PydanticUndefined ) –

    Button id attribute

  • classes (list[str] | None, default: None ) –

    CSS classes for the button

  • disabled (bool, default: False ) –

    Whether button is disabled

  • form (Any, default: PydanticUndefined ) –

    Form element the button is associated with

  • formaction (Any, default: PydanticUndefined ) –

    URL where form data is sent when button is clicked

  • formenctype (Any, default: PydanticUndefined ) –

    How form data is encoded when button is clicked

  • formmethod (Any, default: PydanticUndefined ) –

    HTTP method when button is clicked

  • formnovalidate (bool, default: False ) –

    Whether form validation is bypassed when button is clicked

  • formtarget (Any, default: PydanticUndefined ) –

    Where to display response when button is clicked

  • col_class (str | None, default: None ) –

    Bootstrap column class for horizontal layout (e.g., "col-md-4")

  • template

    Jinja2 template for rendering the field

  • **kwargs (Any, default: {} ) –

    Additional button attributes

Returns:

  • Any

    A Pydantic Field configured for submit button

Example

Basic submit button

submit = SubmitButtonField("Save Changes")

Customized submit button

submit = SubmitButtonField(
    text="Create Account",
    classes=["btn", "btn-primary", "btn-lg"],
    id="create-account-btn"
)

Button with form attributes

delete_btn = SubmitButtonField(
    text="Delete",
    button_type="submit",
    formmethod="DELETE",
    formnovalidate=True,
    classes=["btn", "btn-danger"]
)

TagField

TagField(
    default: Any = PydanticUndefined,
    *,
    separator: str = ",",
    placeholder: str = "Enter tags separated by commas",
    max_tags: int | None = None,
    tag_pattern: str | None = None,
    badge_class: str = "badge bg-primary text-white",
    show_validation: bool = True,
    name: Any = PydanticUndefined,
    id: Any = PydanticUndefined,
    label: Any = PydanticUndefined,
    title: str = PydanticUndefined,
    description: str = PydanticUndefined,
    required: bool = False,
    hidden: bool = False,
    disabled: bool = False,
    **kwargs: Any,
) -> Any

Create a tag input form field for comma-separated values.

This field renders as a text input with live tag visualization using Bootstrap badges. It supports tag validation, max tag limits, and custom styling.

Parameters:

  • default (Any, default: PydanticUndefined ) –

    Default value for the field (can be list or comma-separated string)

  • separator (str, default: ',' ) –

    Character used to separate tags (default: comma)

  • placeholder (str, default: 'Enter tags separated by commas' ) –

    Placeholder text for the input field

  • max_tags (int | None, default: None ) –

    Maximum number of tags allowed (None for unlimited)

  • tag_pattern (str | None, default: None ) –

    Regex pattern for individual tag validation

  • badge_class (str, default: 'badge bg-primary text-white' ) –

    Bootstrap badge CSS classes for tag display

  • show_validation (bool, default: True ) –

    Whether to show validation styling (is-valid/is-invalid)

  • name (Any, default: PydanticUndefined ) –

    Field name attribute

  • id (Any, default: PydanticUndefined ) –

    Field id attribute

  • label (Any, default: PydanticUndefined ) –

    Field label for display

  • title (str, default: PydanticUndefined ) –

    Field title

  • description (str, default: PydanticUndefined ) –

    Field description

  • required (bool, default: False ) –

    Whether field is required

  • template

    Jinja2 template for rendering the field

  • **kwargs (Any, default: {} ) –

    Additional field attributes

Returns:

  • Any

    A Pydantic Field configured for tag input

Example

Basic tag field

tags = TagField(label="Tags", default=["python", "javascript"])

Tag field with custom separator

keywords = TagField(
    label="Keywords",
    separator=";",
    placeholder="Enter keywords separated by semicolons"
)

Limited tag field with custom styling

categories = TagField(
    label="Categories",
    max_tags=5,
    badge_class="badge bg-secondary text-white",
    required=True
)

Tag field without validation styling

draft_tags = TagField(
    label="Draft Tags",
    show_validation=False,
    badge_class="badge border border-primary text-primary"
)

model_from_request async

model_from_request(request: Request, model: Type[T]) -> T
model_from_request(
    request: Request, model: None = None
) -> dict
model_from_request(
    request: Request, model: Type[T] | None = None
) -> T | dict

Parse and validate request body against a Pydantic model.

Loads data from path params, query params, and request body (JSON or form), in that order, overriding earlier values. Form fields that allow multiple values (like multi-select) are handled appropriately.

This function can be used to populate a Pydantic model instance from request data, or return a dict of parameters if no model is provided.

Parameters:

  • request (Request) –

    Starlette Request object

  • model (Type[T] | None, default: None ) –

    Pydantic model class to validate against (optional)

Returns:

  • T | dict

    An instance of the Pydantic model if provided, otherwise a dict of parameters.

AppException

AppException(
    detail: str,
    status_code: int = 400,
    code: ErrorCode | str | None = None,
    source: ErrorSource | None = None,
    meta: dict[str, Any] | None = None,
)

Base exception for all application errors with JSON:API compliance.

This exception provides structured error information that can be rendered as either JSON (for API requests) or HTML (for browser requests).

Parameters:

  • detail (str) –

    Human-readable description of the error

  • status_code (int, default: 400 ) –

    HTTP status code (default: 400)

  • code (ErrorCode | str | None, default: None ) –

    Machine-readable error code

  • source (ErrorSource | None, default: None ) –

    Location of the error (JSON pointer, parameter name, etc.)

  • meta (dict[str, Any] | None, default: None ) –

    Additional metadata about the error

Example
raise AppException(
    detail="User with email 'john@example.com' already exists",
    status_code=409,
    code=ErrorCode.DUPLICATE_RESOURCE,
    source=ErrorSource(parameter="email"),
    meta={"email": "john@example.com"}
)

ErrorCode

Error codes for API responses following JSON:API specification.

Attributes:

  • INTERNAL_ERROR

    Internal server error not caused by client request.

  • INVALID_REQUEST

    The request is malformed or contains invalid parameters.

  • INVALID_PARAMETER

    A specific parameter in the request is invalid.

  • NOT_FOUND

    The requested resource could not be found.

  • VALIDATION_ERROR

    The request data failed validation checks.

  • UNAUTHORIZED

    Authentication is required and has failed or not been provided.

  • FORBIDDEN

    Access to the requested resource is forbidden.

  • METHOD_NOT_ALLOWED

    The HTTP method used is not allowed for the requested resource.

INTERNAL_ERROR class-attribute instance-attribute

INTERNAL_ERROR = 'internal_error'

Internal server error not caused by client request.

INVALID_REQUEST class-attribute instance-attribute

INVALID_REQUEST = 'invalid_request'

The request is malformed or contains invalid parameters.

INVALID_PARAMETER class-attribute instance-attribute

INVALID_PARAMETER = 'invalid_parameter'

A specific parameter in the request is invalid.

NOT_FOUND class-attribute instance-attribute

NOT_FOUND = 'not_found'

The requested resource could not be found.

VALIDATION_ERROR class-attribute instance-attribute

VALIDATION_ERROR = 'validation_error'

The request data failed validation checks.

UNAUTHORIZED class-attribute instance-attribute

UNAUTHORIZED = 'unauthorized'

Authentication is required and has failed or not been provided.

FORBIDDEN class-attribute instance-attribute

FORBIDDEN = 'forbidden'

Access to the requested resource is forbidden.

METHOD_NOT_ALLOWED class-attribute instance-attribute

METHOD_NOT_ALLOWED = 'method_not_allowed'

The HTTP method used is not allowed for the requested resource.

ErrorSource

JSON:API error source object indicating where the error originated.

Attributes:

pointer class-attribute instance-attribute

pointer: str | None = None

parameter class-attribute instance-attribute

parameter: str | None = None

header class-attribute instance-attribute

header: str | None = None

context

Jinja2 context builders and custom filters for starlette_templates templates.

Functions:

  • jsonify

    Convert data to a JSON string for embedding in HTML templates.

  • url_for

    Generate URL for a named route.

  • url

    Generate URL for a mounted application.

  • absurl

    Build absolute URL from path.

  • register_jinja_globals_filters

    Register global functions and filters in the Jinja2 environment.

jsonify

jsonify(data: Any, indent: int | None = None) -> Markup

Convert data to a JSON string for embedding in HTML templates.

Uses Pydantic's built-in JSON serialization to handle complex data types like datetime, Decimal, and BaseModel instances.

Parameters:

  • data (Any) –

    The data to serialize to JSON

Returns:

  • Markup

    A Markup-safe JSON string representation of the data

url_for

url_for(
    context: dict, name: str, **path_params: Any
) -> str

Generate URL for a named route.

This function uses @pass_context to access the request from the template context. The request must be added to the context by TemplateRouter or TemplateResponse.

Parameters:

  • context (dict) –

    Jinja2 context (automatically passed by Jinja2)

  • name (str) –

    Route name

  • **path_params (Any, default: {} ) –

    Path parameters for the route

Returns:

  • str

    URL path for the named route

Example

Assuming a route defined as:

async def user_profile(request: Request):
    ...

app = Starlette(routes=[
    Route("/users/{user_id}/profile", user_profile, name="user_profile"),
])

You can generate the URL by name in a template like this:

{{ url_for('user_profile', user_id=123) }}
<!-- Outputs: 'http://example.com/users/123/profile' -->
Note

This is registered as a Jinja2 global by register_jinja_globals_filters() and can be used directly in templates without importing.

url

url(context: dict, name: str, path: str = '/') -> str

Generate URL for a mounted application.

This function builds URLs for Starlette Mount instances by name. It's a convenience wrapper around url_for specifically for mounts.

Parameters:

  • context (dict) –

    Jinja2 context (automatically passed by Jinja2)

  • name (str) –

    Mount name

  • path (str, default: '/' ) –

    Path within the mount (default: "/")

Returns:

  • str

    URL path for the mounted application

Example

Assuming a mount defined as:

app = Starlette(routes=[
    Mount("/static", StaticFiles(directory="static"), name="static_files"),
])

You can generate URLs for files within the mount in a template like this:

{{ url('static_files', '/css/style.css') }}
<!-- Outputs: 'http://example.com/static/css/style.css' -->
Note

For named routes, use url_for instead. This is specifically for Mount instances.

absurl

absurl(context: dict, path: str) -> str

Build absolute URL from path.

Converts a relative path to an absolute URL by combining it with the request's base URL (scheme + host).

Parameters:

  • context (dict) –

    Jinja2 context (automatically passed by Jinja2)

  • path (str) –

    URL path (relative or absolute)

Returns:

  • str

    Full absolute URL with scheme and host

Example

Creates an absolute URL for the given path:

{{ absurl('/path/to/resource') }}
<!-- Outputs: 'http://example.com/path/to/resource' -->
Note

Different from url_for which uses named routes. This takes a literal path.

register_jinja_globals_filters

register_jinja_globals_filters(
    jinja_env: Environment,
    jinja_globals: dict[str, Any] | None = None,
    jinja_filters: dict[str, Callable] | None = None,
) -> None

Register global functions and filters in the Jinja2 environment.

This function adds commonly used utilities to the Jinja2 environment so they can be accessed directly in templates without importing.

Called by JinjaMiddleware during initialization to set up the environment.

Uses setdefault to avoid overriding any custom globals that may have been set, following the same pattern as Starlette's built-in template functions.

Parameters:

  • jinja_env (Environment) –

    The Jinja2 Environment instance

Flow
  1. JinjaMiddleware creates jinja_env with template loaders
  2. Calls this function to register globals/filters
  3. Stores jinja_env in request.state.jinja_env
  4. Templates can use these functions: {{ url_for(...) }}, {{ data|jsonify }}, etc.
  5. @pass_context functions access request from context["request"]