I have a Django site with many pages with its own unique content and markup (as opposed to a single template that is dynamically populated with data). The templates for these pages are based on a common “tool” template, which in turn is based on a “basic” template. Each page also has a JS file that creates scripts for this page. Each page of data covers approximately 3 or 4 places:
- template
- script page (and possibly other static statistics)
- a central “tool registry” that contains things like name, description and categories of tools
- for some tools, a set of template tags to create some HTML construct specific to this page (for example, data for presentation in a table).
However, although each page has a unique layout and content, I still want to be able to share commonly used parameterized HTML snippets between pages. For example, on one page there is an entry with a drop-down button, which, 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 would like to make a redefined parameterized function / template / tag that allows me to insert a structure such as, for example, "group identifier", "list of entries", "left / right button position", "default value".
So far, I see how to do this:
- As a template that has fairly limited syntax and makes it difficult to execute something like a list of such entries:
['Entry 1', 'Entry 2'] - As a template, passing data to the context through the view (I really don’t like it because I will distribute the contents of the pages even more).
- Like a template tag, creating HTML as a big nasty string
- As a template tag using an XML library such as lxml, which is a fairly flexible method, but suffers from detailed syntax, excessive complexity, and I still get the data into the tag from the template!
None of this looks like a neat, reusable, and loosely coupled way to handle this (for example, if I go to Bootstrap 4 in the future, I may have to overwrite these components, and I would probably have to do this only once). Having a library of such components will also facilitate the creation of future pages. 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 mentioned below by Wolph, I avoided using a clumsy construct like this
{% with [1,2,3] as items %} {% my_tag items.split %} {% endwith %}
in the following way:
@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 the variables as follows:
{% input_with_dropdown 'Common baudrates' '9600 48000 115200' 115200 'baudrate-input' 0 %}