Guard against multi-line {# #} template comments

Django's {# #} is single-line only -- its lexer regex is not DOTALL -- so a
multi-line one is not a comment at all and renders to the page as text. It shipped
into the clubs list, where the archived row read:

    Probe Retired probe-retired {# An archived club's subdomain does not... #}

A test now walks every template and fails on a {# without a closing #} on the same
line, since this is an easy habit to fall back into and the failure is invisible
until someone looks at the rendered page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 01:24:19 +02:00
parent 192fe5ad0e
commit 3a6dc00e05
2 changed files with 109 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
{% load lucide %}
{% comment %}
The club table, shared by the dashboard and the clubs list so the two cannot drift apart.
Health, not vanity: a member total says nothing you can act on, while "no coach",
"nothing scheduled", "€ owed" and "no admins" each name something somebody has to go and
fix. Every column is annotated by clubs_with_health() in a single query.
Expects: clubs (from clubs_with_health), and optionally empty_message.
{% endcomment %}
<div class="overflow-x-auto">
<table class="table">
<thead>
<tr>
<th>Club</th>
<th class="text-right">Members</th>
<th class="text-right">Unpaid</th>
<th class="text-right">Owed</th>
<th class="text-right">Teams</th>
<th class="text-right">Upcoming</th>
<th class="text-right">Admins</th>
</tr>
</thead>
<tbody>
{% for club in clubs %}
<tr>
<td>
<a class="link link-hover font-medium" href="{% url 'controlpanel:club_detail' club.pk %}">{{ club.name }}</a>
<div class="mt-1 flex flex-wrap items-center gap-1">
<span class="text-xs opacity-60">{{ club.slug }}</span>
{% if club.is_archived %}
{% comment %}
An archived club's subdomain does not resolve, so "dormant" and
"no season" would be noise: of course nothing is scheduled.
{% endcomment %}
<span class="badge badge-warning badge-xs gap-1">{% lucide "archive" size=10 %} Archived</span>
{% else %}
{% if not club.has_season %}<span class="badge badge-warning badge-xs gap-1">{% lucide "calendar-x" size=10 %} No season</span>{% endif %}
{% if not club.upcoming_events %}<span class="badge badge-ghost badge-xs gap-1">{% lucide "moon-star" size=10 %} Dormant</span>{% endif %}
{% endif %}
</div>
</td>
<td class="text-right tabular-nums">{{ club.active_members }}</td>
<td class="text-right tabular-nums {% if club.unpaid_members %}text-warning{% endif %}">{{ club.unpaid_members }}</td>
<td class="text-right tabular-nums {% if club.outstanding %}font-semibold text-error{% endif %}">€{{ club.outstanding|floatformat:2 }}</td>
<td class="text-right tabular-nums">
{{ club.team_count }}
{% if club.teams_without_coach %}
<span class="badge badge-error badge-xs ml-1" title="Teams with nobody able to pick the squad">{{ club.teams_without_coach }} no coach</span>
{% endif %}
</td>
<td class="text-right tabular-nums">{{ club.upcoming_events }}</td>
<td class="text-right tabular-nums {% if not club.admin_count %}text-error{% endif %}">{{ club.admin_count }}</td>
</tr>
{% empty %}
<tr>
<td colspan="7" class="text-center opacity-60">{{ empty_message|default:"No clubs yet." }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>