Custom Globals

Add global functions and variables

2 min read 445 words

Globals are available in all templates without explicit passing.

Add Variables

from kida import Environment

env = Environment()

env.add_global("site_name", "My Site")
env.add_global("current_year", 2024)
env.add_global("debug_mode", False)

Template usage:

<title>{{ site_name }}</title>
<footer>&copy; {{ current_year }}</footer>

Add Functions

from datetime import datetime

def now():
    return datetime.now()

def format_date(dt, pattern="%Y-%m-%d"):
    return dt.strftime(pattern)

env.add_global("now", now)
env.add_global("format_date", format_date)

Template usage:

<p>Generated: {{ format_date(now()) }}</p>
<p>Today: {{ format_date(now(), "%B %d, %Y") }}</p>

Add Classes

from collections import namedtuple

# Make types available
env.add_global("Counter", Counter)
env.add_global("namedtuple", namedtuple)

Built-in Globals

Kida includes common Python builtins:

  • range,len,str,int,float,bool
  • dict,list,set,tuple
  • abs,min,max,sum
  • sorted,reversed,enumerate,zip
  • map,filter

Common Patterns

Site Configuration

site_config = {
    "name": "My Site",
    "url": "https://example.com",
    "author": "Jane Doe",
}

env.add_global("site", site_config)
<a href="{{ site.url }}">{{ site.name }}</a>
<meta name="author" content="{{ site.author }}">

Utility Functions

import json
from urllib.parse import urlencode

env.add_global("json_encode", json.dumps)
env.add_global("urlencode", urlencode)
<script>const data = {{ json_encode(config) }};</script>
<a href="/search?{{ urlencode(params) }}">Search</a>

Feature Flags

features = {
    "dark_mode": True,
    "beta_features": False,
    "analytics": True,
}

env.add_global("features", features)
{% if features.dark_mode %}
    <link rel="stylesheet" href="/css/dark.css">
{% end %}

{% if features.analytics %}
    {% include "analytics.html" %}
{% end %}

Request Context (Web)

def get_request_context(request):
    return {
        "user": request.user,
        "path": request.path,
        "is_authenticated": request.user.is_authenticated,
    }

# Per-request globals
env.add_global("request", get_request_context(request))

Translation Function

import gettext

def _(text):
    return translations.gettext(text)

env.add_global("_", _)
env.add_global("gettext", _)
<h1>{{ _("Welcome") }}</h1>
<p>{{ _("Hello, {}!").format(user.name) }}</p>

Dynamic Globals

For per-request values, update globals before rendering:

def render_with_context(template_name, **context):
    # Add request-specific globals
    env.add_global("current_user", get_current_user())
    env.add_global("csrf_token", generate_csrf())

    return env.render(template_name, **context)

Object as Namespace

Group related globals:

class Helpers:
    @staticmethod
    def format_date(dt, pattern="%Y-%m-%d"):
        return dt.strftime(pattern)

    @staticmethod
    def truncate(text, length=100):
        if len(text) <= length:
            return text
        return text[:length] + "..."

env.add_global("helpers", Helpers)
{{ helpers.format_date(post.date) }}
{{ helpers.truncate(post.content, 200) }}

Best Practices

Immutable Configuration

# ✅ Configuration object
env.add_global("config", frozendict(settings))

# ❌ Mutable global
env.add_global("settings", mutable_dict)

Clear Naming

# ✅ Descriptive names
env.add_global("site_config", config)
env.add_global("format_currency", format_money)

# ❌ Vague names
env.add_global("c", config)
env.add_global("f", format_money)

Avoid Side Effects

# ✅ Pure function
env.add_global("add", lambda a, b: a + b)

# ❌ Function with side effects
def log_and_add(a, b):
    print(f"Adding {a} + {b}")  # Side effect
    return a + b

See Also