Pagination and ordering.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Víðir Valberg Guðmundsson 2023-01-12 17:31:34 +01:00
parent 26e06dfaea
commit 659577aaac
5 changed files with 98 additions and 7 deletions

View File

@ -11,7 +11,8 @@ run:
${DOCKER_COMPOSE} up
setup_venv:
python3.10 -m venv venv;
rm -rf venv
python3.11 -m venv venv;
venv/bin/python -m pip install wheel setuptools;
venv/bin/python -m pip install docker-compose pre-commit boto3 pip-tools;

View File

@ -41,7 +41,7 @@ def get_memberships(
def get_members():
return Member.objects.all().annotate_membership()
return Member.objects.all().annotate_membership().order_by("username")
def get_member(*, member_id: int) -> Member:

View File

@ -40,6 +40,7 @@ def members_admin(request):
return render_list(
request=request,
paginate_by=20,
objects=users,
columns=[
("username", _("Username")),

View File

@ -3,11 +3,19 @@
{% block content %}
<h1>
Users <small class="text-muted">{{ total_count }}</small>
</h1>
<table class="table table-striped">
<thead>
<tr>
{% for column in columns %}
<th scope="col">{{ column }}</th>
{% for column, column_label in columns %}
<th scope="col">
<a href="?order_by={% if order_by == column %}-{% endif %}{{ column }}">
{{ column_label }}
</a>
</th>
{% endfor %}
{% if row_actions %}
<th scope="col">{% trans "Actions" %}</th>
@ -32,4 +40,62 @@
{% endfor %}
</table>
{% if is_paginated %}
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
{% if not page.has_previous %}
<li class="page-item disabled">
<a class="page-link">
{% trans "Previous" %}
</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page.previous_page_number }} %}">
{% trans "Previous" %}
</a>
</li>
{% endif %}
{% if page.number|add:'-3' > 1 %}
<li class="page-item">
<a class="page-link" href="?page={{ page.number|add:'-4' }}">&hellip;</a>
</li>
{% endif %}
{% for i in page.paginator.page_range %}
{% if page.number == i %}
<li class="active page-item">
<a href="" class="page-link">{{ i }}</a>
</li>
{% elif i > page.number|add:'-4' and i < page.number|add:'4' %}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if page.paginator.num_pages > page.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ page.number|add:'4' }}">&hellip;</a></licl>
{% endif %}
{% if not page.has_next %}
<li class="page-item disabled">
<a class="page-link">
{% trans "Next" %}
</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page.next_page_number }}">
{% trans "Next" %}
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endblock %}

View File

@ -1,6 +1,9 @@
import contextlib
from dataclasses import dataclass
from django.contrib.sites.shortcuts import get_current_site as django_get_current_site
from django.core.exceptions import FieldError
from django.core.paginator import Paginator
from django.db.models import Model
from django.http import HttpRequest
from django.http import HttpResponse
@ -50,6 +53,7 @@ def render_list(
columns: list[tuple[str, str]],
row_actions: list[RowAction] = None,
list_actions: list[tuple[str, str]] = None,
paginate_by: int = None,
) -> HttpResponse:
"""
Render a list of objects with a table.
@ -57,6 +61,19 @@ def render_list(
# TODO: List actions
total_count = len(objects)
order_by = request.GET.get("order_by")
if order_by:
with contextlib.suppress(FieldError):
objects = objects.order_by(order_by)
if paginate_by:
paginator = Paginator(object_list=objects, per_page=paginate_by)
page = paginator.get_page(request.GET.get("page"))
objects = page.object_list
rows = []
for obj in objects:
row = Row(
@ -65,15 +82,21 @@ def render_list(
)
rows.append(row)
column_labels = [column[1] for column in columns]
context = base_view_context(request) | {
"rows": rows,
"columns": column_labels,
"columns": columns,
"row_actions": row_actions,
"list_actions": list_actions,
"total_count": total_count,
"order_by": order_by,
}
if paginate_by:
context |= {
"page": page,
"is_paginated": True,
}
return render(
request=request,
template_name="utils/list.html",