Skip to main content

Template Functions

Framefox provides powerful built-in functions that are available in all your Jinja2 templates. These functions are automatically registered as global template variables, making them easy to use without any imports or configuration.

url_for()

Generate URLs from named routes with type-safe parameters.

Syntax

{{ url_for('route.name', param1=value1, param2=value2) }}

Usage

<!-- Simple route -->
<a href="{{ url_for('user.index') }}">All Users</a>

<!-- Route with parameters -->
<a href="{{ url_for('user.show', id=user.id) }}">View User</a>

<!-- Route with multiple parameters -->
<a href="{{ url_for('product.detail', category='electronics', id=42) }}">
    View Product
</a>

In Controllers

Define named routes using the @Route decorator:
from framefox.core.routing.decorator.route import Route
from framefox.core.controller.abstract_controller import AbstractController

class UserController(AbstractController):
    
    @Route("/users", "user.index", methods=["GET"])
    async def index(self):
        users = await self.user_repository.find_all()
        return self.render("user/index.html", {"users": users})
    
    @Route("/users/{id}", "user.show", methods=["GET"])
    async def show(self, id: int):
        user = await self.user_repository.find(id)
        return self.render("user/show.html", {"user": user})

Benefits

  • Decoupled URLs: Change route paths without updating templates
  • Type-safe: Parameter validation at runtime
  • Error handling: Returns # if route not found (logged as error)

asset()

Generate URLs for static assets with automatic versioning.

Syntax

{{ asset('path/to/file.ext', versioning=True) }}

Usage

<!-- CSS files -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<link href="{{ asset('css/dashboard.css') }}" rel="stylesheet">

<!-- JavaScript files -->
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ asset('js/charts.js') }}"></script>

<!-- Images -->
<img src="{{ asset('images/logo.png') }}" alt="Logo">
<img src="{{ asset('images/hero-banner.jpg') }}" alt="Banner">

<!-- Disable versioning -->
<link href="{{ asset('css/external.css', versioning=False) }}" rel="stylesheet">

How Versioning Works

  1. File exists: Uses MD5 hash of file modification time
    /css/app.css?v=a3f8b9c2
    
  2. File not found: Uses current timestamp
    /css/app.css?v=1709654321
    

Benefits

  • Cache busting: Automatic version parameters force browser refresh
  • Performance: Browsers cache assets until files change
  • CDN-friendly: Works with content delivery networks

csrf_token()

Generate and return a CSRF token for form protection.

Syntax

{{ csrf_token() }}

Usage

<!-- Basic form with CSRF protection -->
<form method="POST" action="{{ url_for('user.create') }}">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
    
    <input type="text" name="name" placeholder="Name" required>
    <input type="email" name="email" placeholder="Email" required>
    
    <button type="submit">Create User</button>
</form>

<!-- Login form -->
<form method="POST" action="{{ url_for('auth.login') }}">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
    
    <input type="email" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">
    
    <button type="submit">Login</button>
</form>

How It Works

  1. Generates a unique token for the session
  2. Stores the token in the session
  3. Returns the token value for the form
  4. Server validates the token on form submission

Security

  • Required for POST/PUT/DELETE: Protects against CSRF attacks
  • Session-based: Each user session has a unique token
  • Automatic validation: Framework validates tokens automatically

current_user

Access the currently authenticated user object.

Syntax

{{ current_user }}
{{ current_user.property }}

Usage

<!-- Display user info -->
{% if current_user %}
    <div class="user-profile">
        <p>Welcome, {{ current_user.name }}!</p>
        <p>Email: {{ current_user.email }}</p>
        <a href="{{ url_for('auth.logout') }}">Logout</a>
    </div>
{% else %}
    <a href="{{ url_for('auth.login') }}">Login</a>
{% endif %}

<!-- Conditional navigation -->
<nav>
    <a href="{{ url_for('home') }}">Home</a>
    
    {% if current_user %}
        <a href="{{ url_for('dashboard') }}">Dashboard</a>
        <a href="{{ url_for('user.profile') }}">Profile</a>
    {% else %}
        <a href="{{ url_for('auth.register') }}">Register</a>
    {% endif %}
</nav>

<!-- Role-based display -->
{% if current_user and current_user.is_admin %}
    <a href="{{ url_for('admin.panel') }}">Admin Panel</a>
{% endif %}

User Properties

Access any property defined on your user entity:
{{ current_user.id }}
{{ current_user.name }}
{{ current_user.email }}
{{ current_user.created_at }}
{{ current_user.is_active }}

get_flash_messages()

Retrieve session-based flash messages for one-time notifications.

Syntax

{{ get_flash_messages() }}

Usage

<!-- Display all flash messages -->
{% for category, messages in get_flash_messages().items() %}
    {% for message in messages %}
        <div class="alert alert-{{ category }}">
            {{ message }}
        </div>
    {% endfor %}
{% endfor %}

<!-- Styled flash messages -->
{% set flash_messages = get_flash_messages() %}
{% if flash_messages %}
    <div class="flash-container">
        {% if flash_messages.success %}
            {% for message in flash_messages.success %}
                <div class="alert success">✓ {{ message }}</div>
            {% endfor %}
        {% endif %}
        
        {% if flash_messages.error %}
            {% for message in flash_messages.error %}
                <div class="alert error">✗ {{ message }}</div>
            {% endfor %}
        {% endif %}
        
        {% if flash_messages.warning %}
            {% for message in flash_messages.warning %}
                <div class="alert warning">⚠ {{ message }}</div>
            {% endfor %}
        {% endif %}
        
        {% if flash_messages.info %}
            {% for message in flash_messages.info %}
                <div class="alert info">ℹ {{ message }}</div>
            {% endfor %}
        {% endif %}
    </div>
{% endif %}

Setting Flash Messages in Controllers

class UserController(AbstractController):
    
    @Route("/users/create", "user.create", methods=["POST"])
    async def create(self, request: Request):
        # Create user logic...
        
        # Add flash message
        self.flash("success", "User created successfully!")
        
        # Redirect to list
        return self.redirect(self.generate_url("user.index"))
    
    @Route("/users/{id}/delete", "user.delete", methods=["POST"])
    async def delete(self, id: int):
        try:
            # Delete user logic...
            self.flash("success", "User deleted successfully!")
        except Exception as e:
            self.flash("error", f"Failed to delete user: {str(e)}")
        
        return self.redirect(self.generate_url("user.index"))

Message Categories

Common categories include:
  • success - Successful operations
  • error - Error messages
  • warning - Warning messages
  • info - Informational messages
You can use any category name that fits your application.

Additional Global Variables

request

Access the current HTTP request:
<p>Current path: {{ request.url.path }}</p>
<p>Method: {{ request.method }}</p>
<p>Query params: {{ request.query_params }}</p>

dump()

Debug helper to pretty-print any object:
<pre>{{ dump(user) }}</pre>
<pre>{{ dump(request) }}</pre>

Complete Example

<!DOCTYPE html>
<html>
<head>
    <title>User Dashboard</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <!-- Flash messages -->
    {% for category, messages in get_flash_messages().items() %}
        {% for message in messages %}
            <div class="alert alert-{{ category }}">{{ message }}</div>
        {% endfor %}
    {% endfor %}
    
    <!-- User info -->
    {% if current_user %}
        <div class="user-info">
            <p>Welcome, {{ current_user.name }}!</p>
        </div>
    {% endif %}
    
    <!-- User list -->
    <h1>Users</h1>
    {% for user in users %}
        <div class="user-card">
            <h3>{{ user.name }}</h3>
            <a href="{{ url_for('user.show', id=user.id) }}">View Profile</a>
        </div>
    {% endfor %}
    
    <!-- Create form -->
    <form method="POST" action="{{ url_for('user.create') }}">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
        <input type="text" name="name" required>
        <button type="submit">Create User</button>
    </form>
    
    <script src="{{ asset('js/app.js') }}"></script>
</body>
</html>

Build docs developers (and LLMs) love