Mdp11
Mdp11

Reputation: 572

Dynamic template tags in django

I'm building an html page in Django, which has the following structure:

{% extends 'main/base_template.html' %}
{% load filters %}

{% block main_window %}
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
    <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
        <h1 class="h2">Stuff</h1>
    </div>
    <div class="row mb-3">
        <div class="col-12 col-md-6">
            {% include 'main/stuff/stuff_A.html' %}
        </div>
        <div class="col-12 col-md-6">
            {% include 'main/stuff/stuff_B.html' %}
        </div>
    </div>
    <div class="row mb-3">
        <div class="col-12 col-md-6">
            {% include 'main/stuff/stuff_C.html' %}
        </div>
        <div class="col-12 col-md-6">
            {% include 'main/stuff/stuff_D.html' %}
        </div>
    </div>
{% endblock %}

And each of the stuff_X html file has the same structure, for example:

<div class="row mb-3">
    <div class="table-responsive">
        <table class="table table-striped table-sm caption-top" style="width:40em">
            <caption>Data</caption>
            <thead>
            <tr>
                <th scope="col">Data1</th>
                <th scope="col">Data2</th>
                <th scope="col">Data3</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td id="stuff_a_data1" style="width:5em">{{ stuff_a.data1 }}</td>
                <td id="stuff_a_data2" style="width:5em">{{ stuff_a.data2 }}</td>
                <td id="stuff_a_data3" style="width:5em">{{ stuff_a.data2 }}</td>
            </tr>
            </tbody>
        </table>
    </div>
</div>

So the only things that actually change are some ids and the name of the data to be retrieved from the django context.

Are there any mechanisms that allow me to write generic pages for cases like this? Cause currently I am handling 4 (almost) identical pages, adding snippets of code in each of them when I need to modify something.

Thanks in advance!

Upvotes: 1

Views: 385

Answers (2)

nigel222
nigel222

Reputation: 8202

I think you can generalize {{ stuff_a.data1 }} to {{ foo.data1}} by using

{% with stuff_a as foo, 'stuff_a' as foo_id_tag %} 
        {% include 'main/stuff/foo.html' %}
{% endwith %}

provided that the templates are, indeed, identical in form, or similar enough that you can steer them with {%if ... %}. (The ids would become id="{{foo_id_tag}}_data1" etc. )

The other way, which isn't hard, is to use format_html in your python code to generate stuff which you them pass to the template through the context. Or use a property on the relevant model. Something like

class Foo ( models.Model):
    ...

    @property
    def bar (self):
        bar = max( self.a*3 - self.b, 0 ) 
        return f"{bar:.4}" 

so you can refer to {{foo.bar}} in your template, which can't itself do even trivial arithmetic on foo's fields.

Edit: I had forgotten that with functionality has been baked into %include since Django 1.something. So, more elegantly,

{% include 'main/stuff/foo.html' with foo = stuff_a, foo_id_tag = 'stuff_a' %}

Upvotes: 1

reppon
reppon

Reputation: 83

Not sure if that's what you need but you should be able to concatenate strings with the add template filter:

{% with 'main/stuff/stuff_'|add:your_variable|add:'.html' as filename %}
  {% include filename %}
{% endwith %}

You'll need to pass your_variable from your views.py, obviously.

Upvotes: 1

Related Questions