CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-wagtail

A Django content management system with a user-friendly interface and powerful features for building websites and applications.

Overview
Eval results
Files

templates.mddocs/

Template System

Template tags for page URLs, content rendering, and template utilities for building Wagtail-powered front-ends. Wagtail provides comprehensive template integration with Django's template system.

Capabilities

Core Template Tags

Essential template tags for page navigation, URL generation, and content rendering.

def pageurl(page, request=None):
    """
    Get the URL for a page, with optional request context for relative URLs.
    
    Usage in templates: {% pageurl page %}
    
    Parameters:
        page (Page): Page object to get URL for
        request (HttpRequest): Optional request for relative URL generation
        
    Returns:
        str: URL path for the page (relative by default)
    """

def fullpageurl(page, request=None):
    """
    Get the absolute URL for a page including domain.
    
    Usage in templates: {% fullpageurl page %}
    
    Parameters:
        page (Page): Page object to get URL for
        request (HttpRequest): Optional request for domain detection
        
    Returns:
        str: Absolute URL including protocol and domain
    """

def slugurl(slug, request=None):
    """
    Get page URL by slug lookup within the current site.
    
    Usage in templates: {% slugurl 'my-page-slug' %}
    
    Parameters:
        slug (str): Page slug to find and link to
        request (HttpRequest): Optional request for site context
        
    Returns:
        str: URL for the page with matching slug, or empty string if not found
    """

def wagtail_site(request=None):
    """
    Get the current Site object for use in templates.
    
    Usage in templates: {% wagtail_site as current_site %}
    
    Parameters:
        request (HttpRequest): Current request for site detection
        
    Returns:
        Site: Current Site object with hostname, root_page, etc.
    """

def include_block(block_value, context=None):
    """
    Render a StreamField block with its template.
    
    Usage in templates: {% include_block page.body %}
    
    Parameters:
        block_value (StreamValue): StreamField content to render
        context (dict): Additional template context
        
    Returns:
        str: Rendered HTML for all blocks in the StreamField
    """

def wagtail_version():
    """
    Get the current Wagtail version string.
    
    Usage in templates: {% wagtail_version %}
    
    Returns:
        str: Wagtail version (e.g., "4.1.0")
    """

Rich Text Filters

Template filters for processing and rendering rich text content safely.

def richtext(value):
    """
    Process rich text content for safe HTML rendering.
    
    Usage in templates: {{ page.body|richtext }}
    
    Processes rich text to:
    - Convert internal page links to proper URLs
    - Process document download links  
    - Handle embedded content
    - Apply security filtering
    
    Parameters:
        value (str): Raw rich text content from RichTextField
        
    Returns:
        SafeString: Processed HTML safe for rendering
    """

def linebreaks_richtext(value):
    """
    Convert line breaks in rich text to proper HTML paragraphs.
    
    Usage in templates: {{ content|linebreaks_richtext }}
    
    Parameters:
        value (str): Rich text content with line breaks
        
    Returns:
        SafeString: Content with proper paragraph tags
    """

Image Template Tags

Template tags for rendering images with automatic rendition generation.

def image(image, filter_spec, attrs=None):
    """
    Generate an image rendition and return HTML img tag or rendition object.
    
    Usage in templates: 
    {% image page.photo fill-400x300 %}
    {% image page.photo width-800 as hero %}
    
    Parameters:
        image (Image): Image object to render
        filter_spec (str): Image operations to apply (e.g., 'fill-400x300')
        attrs (dict): Additional HTML attributes for img tag
        
    Returns:
        str or Rendition: HTML img tag or rendition object (if using 'as' syntax)
    """

def responsive_image(image, sizes=None, attrs=None):
    """
    Generate responsive image with multiple renditions and srcset.
    
    Usage in templates: {% responsive_image page.hero_image %}
    
    Parameters:
        image (Image): Image object to make responsive
        sizes (list): List of size specifications for different breakpoints  
        attrs (dict): Additional HTML attributes
        
    Returns:
        str: HTML picture element with responsive images
    """

Page Navigation Tags

Template tags for building navigation menus and page hierarchies.

def get_site_root(request=None):
    """
    Get the root page for the current site.
    
    Usage in templates: {% get_site_root as site_root %}
    
    Parameters:
        request (HttpRequest): Current request for site detection
        
    Returns:
        Page: Root page of the current site
    """

def top_menu(parent, calling_page=None):
    """
    Get top-level menu items from a parent page.
    
    Usage in templates: {% top_menu parent calling_page %}
    
    Parameters:
        parent (Page): Parent page to get children from
        calling_page (Page): Current page for active state detection
        
    Returns:
        QuerySet: Child pages suitable for top-level navigation
    """

def breadcrumbs(calling_page):
    """
    Generate breadcrumb navigation for a page.
    
    Usage in templates: {% breadcrumbs self %}
    
    Parameters:
        calling_page (Page): Current page to generate breadcrumbs for
        
    Returns:
        list: List of ancestor pages from root to current page
    """

Search Template Tags

Template tags for search functionality and query handling.

def search(query_string, model_or_queryset=None, fields=None):
    """
    Perform search from templates.
    
    Usage in templates: {% search "query" as search_results %}
    
    Parameters:
        query_string (str): Search query
        model_or_queryset: Model or QuerySet to search
        fields (list): Fields to search in
        
    Returns:
        SearchResults: Search results with pagination support
    """

def paginate(page_list, per_page, page_number):
    """
    Paginate a list of items for template display.
    
    Usage in templates: {% paginate items 10 request.GET.page %}
    
    Parameters:
        page_list (list): Items to paginate
        per_page (int): Number of items per page
        page_number (int): Current page number
        
    Returns:
        Page: Paginated page object with items and navigation
    """

Utility Template Tags

General utility template tags for common Wagtail operations.

def get_page_by_slug(slug, parent=None):
    """
    Get a page by its slug within an optional parent.
    
    Usage in templates: {% get_page_by_slug 'about' as about_page %}
    
    Parameters:
        slug (str): Page slug to find
        parent (Page): Optional parent page to search within
        
    Returns:
        Page: Found page or None if not found
    """

def get_pages_by_type(page_type, parent=None):
    """
    Get pages of a specific type.
    
    Usage in templates: {% get_pages_by_type 'blog.BlogPage' as blog_pages %}
    
    Parameters:
        page_type (str): Page type in 'app.ModelName' format
        parent (Page): Optional parent to search within
        
    Returns:
        QuerySet: Pages of the specified type
    """

def get_site_setting(setting_name, site=None):
    """  
    Get a site-specific setting value.
    
    Usage in templates: {% get_site_setting 'contact_email' as contact %}
    
    Parameters:
        setting_name (str): Name of the setting to retrieve
        site (Site): Optional site (defaults to current site)
        
    Returns:
        Any: Setting value or None if not found
    """

Usage Examples

Basic Page Templates

<!-- Base template: base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}{{ page.seo_title|default:page.title }} - {{ site.site_name }}{% endblock %}</title>
    <meta name="description" content="{{ page.search_description }}">
    {% load wagtailcore_tags %}
</head>
<body class="{% block body_class %}{% endblock %}">
    <header>
        {% get_site_root as site_root %}
        <nav>
            <a href="{% pageurl site_root %}">{{ site.site_name }}</a>
            {% top_menu site_root self as menu_items %}
            <ul>
                {% for item in menu_items %}
                <li><a href="{% pageurl item %}" {% if item == self %}class="active"{% endif %}>{{ item.title }}</a></li>
                {% endfor %}
            </ul>
        </nav>
    </header>
    
    <main>
        {% block breadcrumbs %}
        {% breadcrumbs self as breadcrumb_items %}
        <ol class="breadcrumbs">
            {% for item in breadcrumb_items %}
            <li><a href="{% pageurl item %}">{{ item.title }}</a></li>
            {% endfor %}
        </ol>
        {% endblock %}
        
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; 2023 {{ site.site_name }}. Powered by Wagtail {% wagtail_version %}.</p>
    </footer>
</body>
</html>

<!-- Page template: blog/blog_page.html -->
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}

{% block title %}{{ page.title }} - Blog{% endblock %}

{% block content %}
<article>
    <header>
        <h1>{{ page.title }}</h1>
        <p class="meta">
            Published {{ page.date|date:"F j, Y" }}
            {% if page.author %}by {{ page.author.name }}{% endif %}
        </p>
        {% if page.featured_image %}
        {% image page.featured_image fill-800x400 as hero %}
        <img src="{{ hero.url }}" alt="{{ hero.alt }}" class="hero-image">
        {% endif %}
    </header>
    
    <div class="content">
        <p class="intro">{{ page.intro }}</p>
        {{ page.body|richtext }}
    </div>
    
    <footer>
        <p>
            <a href="{% slugurl 'blog' %}">← Back to Blog</a>
        </p>
    </footer>
</article>
{% endblock %}

StreamField Templates

<!-- StreamField block templates -->

<!-- blocks/heading_block.html -->
<h{{ self.level|default:2 }} class="heading-block">{{ self.text }}</h{{ self.level|default:2 }}>

<!-- blocks/paragraph_block.html -->
<div class="paragraph-block">
    {{ self|richtext }}
</div>

<!-- blocks/image_block.html -->
{% load wagtailimages_tags %}
<figure class="image-block">
    {% image self.image fill-800x600 as img %}
    <img src="{{ img.url }}" alt="{{ img.alt }}" width="{{ img.width }}" height="{{ img.height }}">
    {% if self.caption %}
    <figcaption>{{ self.caption|richtext }}</figcaption>
    {% endif %}
</figure>

<!-- blocks/quote_block.html -->
<blockquote class="quote-block">
    {{ self.quote|richtext }}
    {% if self.attribution %}
    <cite>{{ self.attribution }}</cite>
    {% endif %}
</blockquote>

<!-- Main page template using StreamField -->
{% extends "base.html" %}
{% load wagtailcore_tags %}

{% block content %}
<div class="page-content">
    <h1>{{ page.title }}</h1>
    {% if page.intro %}
    <div class="intro">{{ page.intro|richtext }}</div>
    {% endif %}
    
    <div class="stream-content">
        {% include_block page.body %}
    </div>
</div>
{% endblock %}

Navigation and Menus

<!-- Custom navigation template -->
{% load wagtailcore_tags %}

<!-- Main navigation -->
{% get_site_root as site_root %}
<nav class="main-nav">
    <ul class="nav-list">
        {% top_menu site_root self as main_items %}
        {% for item in main_items %}
        <li class="nav-item {% if item == self or item in self.get_ancestors %}active{% endif %}">
            <a href="{% pageurl item %}" class="nav-link">{{ item.title }}</a>
            
            <!-- Sub-navigation -->
            {% if item.get_children.live %}
            <ul class="sub-nav">
                {% for child in item.get_children.live %}
                <li class="sub-nav-item {% if child == self %}active{% endif %}">
                    <a href="{% pageurl child %}" class="sub-nav-link">{{ child.title }}</a>
                </li>
                {% endfor %}
            </ul>
            {% endif %}
        </li>
        {% endfor %}
    </ul>
</nav>

<!-- Sidebar navigation -->
<aside class="sidebar">
    <h3>In This Section</h3>
    {% get_pages_by_type 'blog.BlogPage' as blog_pages %}
    <ul class="sidebar-nav">
        {% for page in blog_pages.live|slice:":5" %}
        <li><a href="{% pageurl page %}">{{ page.title }}</a></li>
        {% endfor %}
    </ul>
</aside>

<!-- Footer navigation -->
<footer class="site-footer">
    <div class="footer-nav">
        {% get_page_by_slug 'contact' as contact_page %}
        {% get_page_by_slug 'privacy' as privacy_page %}
        {% get_page_by_slug 'terms' as terms_page %}
        
        <ul class="footer-links">
            {% if contact_page %}<li><a href="{% pageurl contact_page %}">{{ contact_page.title }}</a></li>{% endif %}
            {% if privacy_page %}<li><a href="{% pageurl privacy_page %}">{{ privacy_page.title }}</a></li>{% endif %}
            {% if terms_page %}<li><a href="{% pageurl terms_page %}">{{ terms_page.title }}</a></li>{% endif %}
        </ul>
    </div>
</footer>

Image Handling

{% load wagtailimages_tags %}

<!-- Basic image rendering -->
{% if page.hero_image %}
{% image page.hero_image fill-1200x600 as hero %}
<div class="hero" style="background-image: url({{ hero.url }});">
    <h1>{{ page.title }}</h1>
</div>
{% endif %}

<!-- Responsive images -->
{% if page.featured_image %}
{% image page.featured_image fill-400x300 as mobile %}
{% image page.featured_image fill-800x600 as tablet %}  
{% image page.featured_image fill-1200x800 as desktop %}

<picture class="responsive-image">
    <source media="(min-width: 1024px)" srcset="{{ desktop.url }}">
    <source media="(min-width: 768px)" srcset="{{ tablet.url }}">
    <img src="{{ mobile.url }}" alt="{{ page.featured_image.title }}" 
         width="{{ mobile.width }}" height="{{ mobile.height }}">
</picture>
{% endif %}

<!-- Image gallery -->
<div class="image-gallery">
    {% for gallery_image in page.gallery_images.all %}
    {% image gallery_image.image fill-300x200 as thumb %}
    {% image gallery_image.image width-1000 as full %}
    
    <div class="gallery-item">
        <a href="{{ full.url }}" data-lightbox="gallery">
            <img src="{{ thumb.url }}" alt="{{ gallery_image.image.title }}">
        </a>
        {% if gallery_image.caption %}
        <p class="caption">{{ gallery_image.caption }}</p>
        {% endif %}
    </div>
    {% endfor %}
</div>

<!-- Optimized images with WebP -->
{% image page.hero_image fill-1200x600|format-webp as webp_hero %}
{% image page.hero_image fill-1200x600|format-jpeg as jpeg_hero %}

<picture>
    <source srcset="{{ webp_hero.url }}" type="image/webp">
    <img src="{{ jpeg_hero.url }}" alt="{{ page.hero_image.title }}" class="hero-image">
</picture>

Search Templates

<!-- Search form -->
<form action="{% url 'search' %}" method="get" class="search-form">
    <input type="text" name="q" value="{{ query_string }}" placeholder="Search..." required>
    <button type="submit">Search</button>
</form>

<!-- Search results template -->
{% load wagtailcore_tags %}

{% block content %}
<div class="search-results">
    <h1>Search Results</h1>
    
    {% if query_string %}
    <p>You searched for: <strong>{{ query_string }}</strong></p>
    
    {% if search_results %}
    <p>{{ search_results.paginator.count }} result{{ search_results.paginator.count|pluralize }} found</p>
    
    <div class="results-list">
        {% for result in search_results %}
        <article class="search-result">
            <h3><a href="{% pageurl result %}">{{ result.title }}</a></h3>
            <p class="meta">{{ result.content_type.model_class.get_verbose_name }}</p>
            {% if result.search_description %}
            <p>{{ result.search_description }}</p>
            {% endif %}
        </article>
        {% endfor %}
    </div>
    
    <!-- Pagination -->
    {% if search_results.has_other_pages %}
    <nav class="pagination">
        {% if search_results.has_previous %}
        <a href="?q={{ query_string }}&page={{ search_results.previous_page_number }}">← Previous</a>
        {% endif %}
        
        <span class="current">
            Page {{ search_results.number }} of {{ search_results.paginator.num_pages }}
        </span>
        
        {% if search_results.has_next %}
        <a href="?q={{ query_string }}&page={{ search_results.next_page_number }}">Next →</a>
        {% endif %}
    </nav>
    {% endif %}
    
    {% else %}
    <p>No results found.</p>
    {% endif %}
    
    {% endif %}
</div>
{% endblock %}

Custom Template Tags

# templatetags/blog_tags.py
from django import template
from django.utils import timezone
from blog.models import BlogPage

register = template.Library()

@register.inclusion_tag('blog/recent_posts.html')
def recent_blog_posts(count=5):
    """Get recent blog posts for sidebar."""
    posts = BlogPage.objects.live().order_by('-date')[:count]
    return {'posts': posts}

@register.simple_tag
def get_popular_posts(count=5):
    """Get most popular blog posts."""
    return BlogPage.objects.live().order_by('-page_views')[:count]

@register.filter
def reading_time(content):
    """Calculate reading time for content."""
    word_count = len(str(content).split())
    minutes = max(1, word_count // 200)  # 200 words per minute
    return f"{minutes} min read"

@register.inclusion_tag('blog/tag_cloud.html')
def tag_cloud():
    """Generate tag cloud for blog."""
    from django.db.models import Count
    tags = BlogTag.objects.annotate(
        post_count=Count('blogpage')
    ).filter(post_count__gt=0).order_by('-post_count')[:20]
    return {'tags': tags}

# Usage in templates
{% load blog_tags %}

<!-- Recent posts sidebar -->
{% recent_blog_posts 3 %}

<!-- Popular posts -->
{% get_popular_posts 5 as popular %}
<ul>
    {% for post in popular %}
    <li><a href="{% pageurl post %}">{{ post.title }}</a></li>
    {% endfor %}
</ul>

<!-- Reading time -->
<p class="meta">{{ page.body|reading_time }}</p>

<!-- Tag cloud -->
{% tag_cloud %}

Form Templates

<!-- Contact form template -->
{% extends "base.html" %}
{% load wagtailcore_tags %}

{% block content %}
<div class="contact-page">
    <h1>{{ page.title }}</h1>
    
    {% if page.intro %}
    <div class="intro">
        {{ page.intro|richtext }}
    </div>
    {% endif %}
    
    <form action="{% pageurl page %}" method="post" class="contact-form">
        {% csrf_token %}
        
        {% for field in form %}
        <div class="form-field {% if field.errors %}error{% endif %}">
            {{ field.label_tag }}
            {{ field }}
            {% if field.help_text %}
            <p class="help-text">{{ field.help_text }}</p>
            {% endif %}
            {% for error in field.errors %}
            <p class="error-message">{{ error }}</p>
            {% endfor %}
        </div>
        {% endfor %}
        
        <button type="submit" class="submit-button">Send Message</button>
    </form>
    
    {% if page.thank_you_text %}
    <div class="thank-you" style="display: none;">
        {{ page.thank_you_text|richtext }}
    </div>
    {% endif %}
</div>
{% endblock %}

Install with Tessl CLI

npx tessl i tessl/pypi-wagtail

docs

admin-interface.md

api.md

content-fields.md

contrib.md

index.md

media.md

page-models.md

search.md

system-integration.md

templates.md

workflows.md

tile.json