Django Sekizai
Django Sekizai (meaning "blocks" in Japanese) is a Django application that provides enhanced template block functionality. It allows developers to define placeholders where content blocks are rendered and, from various places in sub-templates, append unique content to those blocks. This is particularly useful for managing CSS and JavaScript dependencies across complex template structures, ensuring that media files are placed correctly (e.g., CSS in the head, JS at the bottom) and duplicates are automatically ignored. The library is currently at version 4.1.0 and is actively maintained by the django CMS Association, with regular releases aligning with Django's own release cycle.
Common errors
-
You must enable the 'sekizai.context_processors.sekizai' template context processor or use 'sekizai.context.SekizaiContext' to render your templates.
cause Sekizai requires its context processor to be active or `SekizaiContext` to be explicitly used for rendering. This error typically occurs when it's missing from `TEMPLATES['OPTIONS']['context_processors']` in `settings.py` or when using `render_to_response` without `SekizaiContext` in a view or test.fix1. Add `'sekizai.context_processors.sekizai'` to your `TEMPLATES['OPTIONS']['context_processors']` list in `settings.py`. 2. If rendering manually in views or tests, ensure you pass `SekizaiContext` (e.g., `render(request, 'template.html', context=SekizaiContext())`) [6, 14]. -
Invalid block tag: 'render_block', expected 'endblock'
cause This error or similar `Invalid block tag` errors with Sekizai tags often arise when `{% render_block %}` is placed inside another Django template tag that defines a block (like `{% block %}`, `{% if %}`, `{% for %}`).fixEnsure `{% render_block %}` tags are at the root level of your template or directly within static HTML tags (e.g., `<head>`, `<body>`) and not nested within other dynamic block tags [2, 3, 18]. -
Content added with `{% addtoblock %}` is not appearing in the final rendered HTML or is duplicated unexpectedly.cause Common causes include: 1. `{% addtoblock %}` is not wrapped inside a `{% block %}` in an extending template. 2. A parent block containing `{% addtoblock %}` is overridden in a child template without calling `{{ block.super }}`. 3. Expecting duplicated content, but Sekizai's deduplication feature is active.fix1. Always wrap `{% addtoblock %}` within a `{% block %}` tag in inherited templates. 2. If overriding, include `{{ block.super }}` to retain content from parent blocks. 3. Remember Sekizai inherently deduplicates content within a namespace; for multiple identical inclusions, consider making them unique or using different namespaces [1, 3, 11, 13].
Warnings
- gotcha Sekizai enforces uniqueness of content within a block namespace. If you add the same content (e.g., a `<script>` tag with the exact same `src`) multiple times using `addtoblock`, it will only be rendered once.
- gotcha `{% render_block %}` tags must not be placed inside other Django template tag blocks (e.g., `{% block %}`, `{% if %}`, `{% for %}`). This can lead to `TemplateSyntaxError`.
- gotcha When using `{% addtoblock %}` within an extending template, it must be nested inside a `{% block %}` tag from the parent template. If the parent block is overridden in a child template *without* calling `{{ block.super }}`, the `addtoblock` content will be ignored.
- gotcha The `django-compressor` integration with `django-sekizai` does not support offline compression. This means assets added via Sekizai might not be compressed during a `compress` management command if offline compression is enabled.
Install
-
pip install django-sekizai
Imports
- sekizai_tags
{% load sekizai_tags %} - SekizaiContext
from django.template import RequestContext
from sekizai.context import SekizaiContext
- sekizai
INSTALLED_APPS = [ # ... 'sekizai', ] - sekizai.context_processors.sekizai
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ # ... 'sekizai.context_processors.sekizai', ], }, }, ]
Quickstart
# settings.py
INSTALLED_APPS = [
# ...
'sekizai',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'sekizai.context_processors.sekizai', # Add Sekizai context processor
],
},
},
]
# base.html (or your main template)
{% load sekizai_tags %}
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
{% render_block "css" %}
</head>
<body>
<header>...</header>
{% block content %}{% endblock %}
<footer>...
{% render_block "js" %}
</footer>
</body>
</html>
# my_app/templates/my_app/detail.html
{% extends 'base.html' %}
{% load sekizai_tags %}
{% block content %}
<h1>Welcome</h1>
<p>This is my content.</p>
{% addtoblock "css" %}
<link rel="stylesheet" href="/static/css/detail.css">
{% endaddtoblock %}
{% addtoblock "js" %}
<script src="/static/js/detail.js"></script>
<script>
console.log('Detail page loaded!');
</script>
{% endaddtoblock %}
{% endblock %}