diff --git a/Makefile b/Makefile
index 9bb2fc1..9a8a731 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
diff --git a/src/membership/selectors.py b/src/membership/selectors.py
index 77e493d..a23590d 100644
--- a/src/membership/selectors.py
+++ b/src/membership/selectors.py
@@ -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:
diff --git a/src/membership/views.py b/src/membership/views.py
index 165fd5a..43881d4 100644
--- a/src/membership/views.py
+++ b/src/membership/views.py
@@ -40,6 +40,7 @@ def members_admin(request):
return render_list(
request=request,
+ paginate_by=20,
objects=users,
columns=[
("username", _("Username")),
diff --git a/src/utils/templates/utils/list.html b/src/utils/templates/utils/list.html
index a534b64..bb0d5e7 100644
--- a/src/utils/templates/utils/list.html
+++ b/src/utils/templates/utils/list.html
@@ -3,11 +3,19 @@
{% block content %}
+
+ Users {{ total_count }}
+
+
- {% for column in columns %}
- {{ column }} |
+ {% for column, column_label in columns %}
+
+
+ {{ column_label }}
+
+ |
{% endfor %}
{% if row_actions %}
{% trans "Actions" %} |
@@ -32,4 +40,62 @@
{% endfor %}
+ {% if is_paginated %}
+
+
+ {% endif %}
+
{% endblock %}
diff --git a/src/utils/view_utils.py b/src/utils/view_utils.py
index c88849c..9b5b277 100644
--- a/src/utils/view_utils.py
+++ b/src/utils/view_utils.py
@@ -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",