In my application I’m displaying a table that has an svg of an email envelope for each instance of a model. This model has a reverse foreign key to a table that contains emails, so this model can have none, one or multiple emails associated with it. I want to add tooltips to these svgs that show the emails that are associated with the model.
The problem I’m having is that I need to edit an attribute of the a wrapper with the text, and I can’t put the for loop outside of the wrapper because otherwise I’d have an svg for each associated email.
The only solution I can think of is either pregenerating the values for each instance in the view or adding a model method. Is there a way to handle this in the template?
I’m not sure if it’s relevant to the problem but I’m using bootstrap5 and it’s tooltips:
Here’s example code:
# models.py
class Something(models.Model):
name = models.CharField(max_length=255)
class Email(models.Model):
something = models.ForeignKey(Something, on_delete=models.CASCADE)
email = models.EmailField()
<!-- something.html -->
<div data-bs-toggle="tooltip" data-bs-title="{{ something.email.all }}">
<svg xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope text-success"
viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z" />
<title>
<p>{{ something.email.all }}</p>
</title>
</svg>
</div>
Where exactly is the for loop in this template? It’s hard to tell what you’re trying to achieve with the code you’ve given.
Depending upon the specifics as described in the previous response, creating a model method for this would generally be your best solution. You don’t want to perform any sort of real calculation in your template - by design, that’s not what the template language is for. Any significant model-based logic belongs in the model.
When I wrote the question I was thinking of a for loop outside the element, like this:
{% for email in something.email.all %}
<div data-bs-toggle="tooltip" data-bs-title="{{ email }}">
<svg xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope text-success"
viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z" />
<title>
<p>{{ email }}</p>
</title>
</svg>
</div>
{% endfor %}
When I wanted to have the iterated values of the for loop where {{something.email.all}} is in the original question, without repeating svgs. Which is why I asked if it was possible to iterate the values and store them in some kind of variable to then paste them in {{something.email.all}}.
I didn’t know it was possible to put template tags inside attribute strings
, so the following code resolves the problem:
<div data-bs-toggle="tooltip"
data-bs-title="{% for email in something.email.all %}{{ email }}{% endfor %}">
<svg xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope text-success"
viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z" />
<title>
{% for email in something.email.all %}<p>{{ email }}</p>{% endfor %}
</title>
</svg>
</div>