Muestra las etiquetas en tabla con su numero de gastos

El listado de etiquetas era una lista sin mas, sin forma de saber cuales
estaban en uso. Pasa a tabla, en linea con el resto de listados, y anade
una columna con el numero de gastos que usa cada etiqueta.

El contador se calcula con annotate(Count("expenses")) en la vista, en vez
de contar desde la plantilla, para no provocar una query por fila.

Incluye tambien el estado vacio, que la lista no tenia.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
JKuijperM 2026-09-09 15:36:02 +02:00
parent e65b15ccf8
commit 22563df48a
3 changed files with 60 additions and 14 deletions

View File

@ -5,15 +5,34 @@
<a class="btn" href="{% url 'tag_create' %}"> Nueva etiqueta</a>
<ul>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Gastos</th>
<th></th>
</tr>
</thead>
<tbody>
{% for tag in tags %}
<li class="table-actions">
{{ tag.name }}
<tr>
<td>{{ tag.name }}</td>
<td>{{ tag.expense_count }}</td>
<td class="table-actions">
<a href="{% url 'tag_edit' tag.id %}">Editar</a>
<a href="{% url 'tag_delete' tag.id %}" class="danger">Eliminar</a>
</li>
</td>
</tr>
{% empty %}
<li>No hay etiquetas</li>
<tr>
<td colspan="3" class="empty-state">
<p>No hay etiquetas</p>
<a href="{% url 'tag_create' %}">Añade la primera</a>
</td>
</tr>
{% endfor %}
</ul>
</tbody>
</table>
</div>
{% endblock %}

View File

@ -0,0 +1,23 @@
import pytest
from datetime import date
from decimal import Decimal
from django.urls import reverse
from expenses.models import Expense, Tag
pytestmark = pytest.mark.django_db
def test_tag_list_annotates_expense_usage_count(auth_client, user, account, category):
used = Tag.objects.create(owner=user, name="Usada")
unused = Tag.objects.create(owner=user, name="Sin usar")
for _ in range(2):
expense = Expense.objects.create(
owner=user, account=account, category=category, amount=Decimal("10"), date=date.today()
)
expense.tags.add(used)
response = auth_client.get(reverse('tag_list'))
counts = {tag.name: tag.expense_count for tag in response.context["tags"]}
assert counts == {"Usada": 2, "Sin usar": 0}

View File

@ -15,7 +15,7 @@ from .forms import (
)
from django.core.paginator import Paginator
from django.db.models import Sum, ProtectedError
from django.db.models import Sum, Count, ProtectedError
from django.db.models.functions import ExtractMonth, ExtractYear, ExtractDay
from django.contrib.auth.decorators import login_required
@ -635,7 +635,11 @@ def dashboard(request):
@login_required
def tag_list(request):
tags = Tag.objects.filter(owner=request.user)
tags = (
Tag.objects.filter(owner=request.user)
.annotate(expense_count=Count("expenses"))
.order_by("name")
)
return render(
request, "expenses/tag_list.html", {"active_menu": "settings", "tags": tags}