I have a Django website with many pages all with their own unique content and markup (as opposed to a single template that is dynamically filled with data). These pages' templates are derived from a common "tool" template, which in turn derives from a "base" template. Each page also has a JS file which does the scripting for that page. Each pages data is spread around 3 or 4 locations:
However, although each page has a unique layout and content, I still want to be able to share commonly used parametrised HTML "snippets" between pages. For example, one page has an input with a dropdown button that, using Bootstrap, looks like this:
<div class="input-group">
<span class="input-group-btn">
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">
Common baudrates
<span class="caret"></span>
</a>
<ul class="dropdown-menu pull-right" id="common-baudrate-list">
<li><a href='#'>9600</a></li>
<li><a href='#'>115200</a></li>
</ul>
</span>
<input class="form-control" type="text" id="baudrate-input" val="115200">
</div>
I'd like to make a re-uasable parametrised function/template/tag which allows me to put in a structure like this given something like "group ID", "list of entries", "left/right button position", "default value".
The ways I see to do it so far are:
['Entry 1', 'Entry 2']
None of these seem like a neat, re-usable and loosely coupled way to deal with this (for example, if I change up to Bootstrap 4 in future, I may need to re-write these components, and I'd rather have to do it just once). Having a library of components like this will also make future pages easier to construct. Is there a canonical "right" way to do this, or even a commonly used idiom for it?
Edit to show solution implementation
Using inclusion tags as answered below by Wolph, I avoided using a clunky construction like this
{% with [1,2,3] as items %}
{% my_tag items.split %}
{% endwith %}
as follows:
@register.inclusion_tag('components/this_component.html')
def input_with_dropdown(dropdown_title, dropdown_items, default_value, group_id, button_left, *args, **kwargs):
split_char = kwargs['split_char'] if 'split_char' in kwargs else ' '
return {
'dropdown_items': dropdown_items.split(split_char),
'dropdown_title': dropdown_title,
'group_id': group_id,
'default_value' : default_value,
'button_left': button_left
}
And then passing in the variables like this:
{% input_with_dropdown 'Common baudrates' '9600 48000 115200' 115200 'baudrate-input' 0 %}
Have you taken a look at inclusion tags? https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
I believe that these would do exactly what you want, you can still specify parameters but you can just pass along a template to have it render really easily.
Example:
from django import template
register = template.Library()
@register.inclusion_tag('list_results.html')
def list_results(results):
return {
'results': results,
'count': len(results),
}
list_results.html
:
Found {{ count }} results.<br>
<ul>
{% for result in results %}
<li>{{ result }}</li>
{% endfor %}
</ul>