Named Contents Blocks¶
Named contents blocks allow you to pass multiple content sections to a single component, enabling more complex and flexible component designs.
Basic Syntax¶
{% load includecontents %}
{% includecontents "template.html" %}
Default content goes here
{% contents section_name %}Named content goes here{% endcontents %}
{% endincludecontents %}
In the included template, access the content using:
- {{ contents }}
for the default content
- {{ contents.section_name }}
for named sections
Simple Example¶
templates/components/card.html
<div class="card">
<div class="card-body">
{{ contents }}
</div>
{% if contents.footer %}
<div class="card-footer">
{{ contents.footer }}
</div>
{% endif %}
</div>
Usage:
{% load includecontents %}
{% includecontents "components/card.html" %}
<p>This is the main card content.</p>
{% contents footer %}
<button class="btn">Action</button>
{% endcontents %}
{% endincludecontents %}
Result:
<div class="card">
<div class="card-body">
<p>This is the main card content.</p>
</div>
<div class="card-footer">
<button class="btn">Action</button>
</div>
</div>
Multiple Named Sections¶
You can define multiple named content sections:
templates/components/article.html
<article class="article">
{% if contents.header %}
<header class="article-header">
{{ contents.header }}
</header>
{% endif %}
<main class="article-body">
{{ contents }}
</main>
{% if contents.sidebar %}
<aside class="article-sidebar">
{{ contents.sidebar }}
</aside>
{% endif %}
{% if contents.footer %}
<footer class="article-footer">
{{ contents.footer }}
</footer>
{% endif %}
</article>
Usage:
{% includecontents "components/article.html" %}
{% contents header %}
<h1>Article Title</h1>
<p class="meta">Published on {{ article.date }}</p>
{% endcontents %}
<p>This is the main article content...</p>
<p>Multiple paragraphs are supported.</p>
{% contents sidebar %}
<h3>Related Articles</h3>
<ul>
<li><a href="#">Article 1</a></li>
<li><a href="#">Article 2</a></li>
</ul>
{% endcontents %}
{% contents footer %}
<p>Share this article:</p>
<div class="social-buttons">...</div>
{% endcontents %}
{% endincludecontents %}
Conditional Content Blocks¶
Use Django's template conditionals to handle optional content blocks:
templates/components/modal.html
<div class="modal">
{% if contents.header %}
<div class="modal-header">
{{ contents.header }}
<button class="close">×</button>
</div>
{% endif %}
<div class="modal-body">
{{ contents }}
</div>
{% if contents.footer %}
<div class="modal-footer">
{{ contents.footer }}
</div>
{% else %}
<div class="modal-footer">
<button class="btn btn-default">Close</button>
</div>
{% endif %}
</div>
HTML Content Syntax Alternative¶
If you're using the custom template engine, you can use HTML-style syntax for named content blocks:
{% includecontents "components/article.html" %}
{% contents header %}
<h1>Article Title</h1>
<p class="meta">Published on {{ article.date }}</p>
{% endcontents %}
<p>This is the main article content...</p>
{% contents sidebar %}
<h3>Related Articles</h3>
<ul>
<li><a href="#">Article 1</a></li>
</ul>
{% endcontents %}
{% endincludecontents %}
Both syntaxes are equivalent and can be mixed within the same project.
Nested Content Blocks¶
Content blocks can contain Django template logic and even other components:
{% includecontents "components/dashboard.html" %}
<h1>Welcome, {{ user.name }}!</h1>
{% contents widgets %}
{% for widget in user.widgets %}
{% includecontents "components/widget.html" widget=widget %}
{{ widget.content }}
{% endincludecontents %}
{% endfor %}
{% endcontents %}
{% contents footer %}
Last login: {{ user.last_login|date:"M d, Y" }}
{% endcontents %}
{% endincludecontents %}
Best Practices¶
1. Document Expected Content Blocks¶
Add comments to your component templates to document expected content blocks:
<!--
Component: Article Layout
Expected content blocks:
- header (optional): Article title and meta information
- contents (required): Main article content
- sidebar (optional): Related links or additional info
- footer (optional): Social sharing buttons
-->
<article class="article">
<!-- ... component template ... -->
</article>
2. Provide Sensible Defaults¶
Always provide fallbacks for optional content blocks:
<div class="card">
<div class="card-header">
{% if contents.header %}
{{ contents.header }}
{% else %}
<h3>Default Title</h3>
{% endif %}
</div>
<div class="card-body">
{{ contents }}
</div>
</div>
3. Keep Block Names Semantic¶
Use descriptive names that clearly indicate the purpose:
{% contents header %}...{% endcontents %} <!-- ✅ Good -->
{% contents sidebar_content %}...{% endcontents %} <!-- ✅ Good -->
{% contents block1 %}...{% endcontents %} <!-- ❌ Avoid -->
{% contents x %}...{% endcontents %} <!-- ❌ Avoid -->
4. Consider Order and Layout¶
The order of content blocks in your usage doesn't need to match the order in the component template:
{% includecontents "card.html" %}
{% contents footer %}Footer comes first in the code{% endcontents %}
Main content comes after, but renders first in the card
{% contents header %}Header comes last in code{% endcontents %}
{% endincludecontents %}
Common Patterns¶
Layout Components¶
<!-- templates/components/two-column.html -->
<div class="row">
<div class="col-md-8">
{{ contents }}
</div>
<div class="col-md-4">
{{ contents.sidebar }}
</div>
</div>
Form Components¶
<!-- templates/components/form-field.html -->
<div class="form-group">
{% if contents.label %}
<label>{{ contents.label }}</label>
{% endif %}
{{ contents }}
{% if contents.help %}
<small class="form-text">{{ contents.help }}</small>
{% endif %}
{% if contents.errors %}
<div class="invalid-feedback">{{ contents.errors }}</div>
{% endif %}
</div>
Navigation Components¶
<!-- templates/components/nav-section.html -->
<div class="nav-section">
<h3 class="nav-title">{{ contents.title }}</h3>
<ul class="nav-list">
{{ contents }}
</ul>
{% if contents.footer %}
<div class="nav-footer">{{ contents.footer }}</div>
{% endif %}
</div>
Next Steps¶
- Learn about the Wrapif Tag for conditional wrapping
- Explore HTML Component Syntax for a modern alternative
- Check out Component Patterns for advanced usage