# Filters URL: /docs/templates/filters/ Section: templates Tags: templates, filters, globals, kida -------------------------------------------------------------------------------- Built-in Filters Chirp ships with built-in filters that are automatically available in every template. These complement Kida's core filters with web-specific utilities. field_errors Extract validation errors for a single form field from an errors dict. Returns a list of error messages. {% for msg in errors | field_errors("email") %} <p class="error">{{ msg }}</p> {% end %} If the field has no errors, or errors is None, an empty list is returned — so the loop simply produces nothing. Typical usage with form_or_errors(): @app.route("/signup", methods=["POST"]) async def signup(request: Request): result = await form_or_errors(request, SignupForm, "signup.html", "form") if isinstance(result, ValidationError): return result # errors and form values are included # ... process valid data <label>Email</label> <input name="email" value="{{ form.email ?? "" }}"> {% for msg in errors | field_errors("email") %} <span class="field-error">{{ msg }}</span> {% end %} qs Build a URL with query-string parameters. Falsy values are automatically omitted. <a href="{{ '/search' | qs(q=query, page=page) }}">Search</a> {# Output: /search?q=hello&page=2 #} Falsy values (None, "", 0, False) are dropped: {{ '/items' | qs(q=query, category=category, page=none) }} {# If category is "", outputs: /items?q=hello #} Appends to existing query strings: {{ '/search?q=hello' | qs(page=2) }} {# Output: /search?q=hello&page=2 #} Special characters are URL-encoded: {{ '/search' | qs(q="hello world") }} {# Output: /search?q=hello%20world #} Custom Filters Filters transform values in templates. Register them with @app.template_filter(): @app.template_filter() def currency(value: float) -> str: return f"${value:,.2f}" @app.template_filter() def pluralize(count: int, singular: str, plural: str) -> str: return singular if count == 1 else plural Use them in templates with the pipe syntax: <span class="price">{{ product.price | currency }}</span> <span>{{ count }} {{ count | pluralize("item", "items") }}</span> Named Filters By default, the function name becomes the filter name. Override it with an argument: @app.template_filter("fmt_date") def format_date(dt: datetime) -> str: return dt.strftime("%B %d, %Y") <time>{{ post.created_at | fmt_date }}</time> Template Globals Globals are functions or values available in every template without being passed in the context: @app.template_global() def site_name() -> str: return "My App" @app.template_global() def current_year() -> int: return datetime.now().year <footer>&copy; {{ current_year() }} {{ site_name() }}</footer> Registration Timing Filters and globals must be registered during the setup phase (before app.run() or the first request). They become part of the kida environment at freeze time. app = App() # Register during setup @app.template_filter() def upper(value: str) -> str: return value.upper() # This works app.run() # Registering after freeze would raise an error Type Safety Filters are regular Python functions with full type annotations. Your IDE provides autocomplete and type checking for filter arguments. @app.template_filter() def truncate(value: str, length: int = 50, suffix: str = "...") -> str: if len(value) <= length: return value return value[:length].rsplit(" ", 1)[0] + suffix Next Steps Rendering -- How templates are rendered App Lifecycle -- When filters are registered API Reference -- Complete API surface -------------------------------------------------------------------------------- Metadata: - Word Count: 462 - Reading Time: 2 minutes