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 ${DOCKER_COMPOSE} up
setup_venv: 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 wheel setuptools;
venv/bin/python -m pip install docker-compose pre-commit boto3 pip-tools; 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(): 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: def get_member(*, member_id: int) -> Member:

View File

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

View File

@ -3,11 +3,19 @@
{% block content %} {% block content %}
<h1>
Users <small class="text-muted">{{ total_count }}</small>
</h1>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
{% for column in columns %} {% for column, column_label in columns %}
<th scope="col">{{ column }}</th> <th scope="col">
<a href="?order_by={% if order_by == column %}-{% endif %}{{ column }}">
{{ column_label }}
</a>
</th>
{% endfor %} {% endfor %}
{% if row_actions %} {% if row_actions %}
<th scope="col">{% trans "Actions" %}</th> <th scope="col">{% trans "Actions" %}</th>
@ -32,4 +40,62 @@
{% endfor %} {% endfor %}
</table> </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 %} {% endblock %}

View File

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