Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions django_admin_react/api/views/recent_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from django_admin_react.api.permissions import forbidden_response
from django_admin_react.api.permissions import is_admin_user
from django_admin_react.api.registry import get_admin_site
from django_admin_react.audit import recent_actions_for_user

# Default / ceiling for the number of entries returned. Django's index
# shows 10; the ceiling keeps a hand-crafted ``?limit=`` from scanning
Expand Down Expand Up @@ -60,12 +61,11 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:

# ``is_admin_user`` guarantees an authenticated user, so pk is set
# (it may be int or str for a custom user model — both are valid
# lookups). Scoped to this user only — Django's own index panel
# filters the same way.
# lookups). Scoped to this user only; the LogEntry query lives in
# ``audit.py`` (outside ``api/``), the designated home for the
# framework audit table — see that module's docstring.
user_pk = cast("str | int", request.user.pk)
entries = list(
LogEntry.objects.filter(user__pk=user_pk).order_by("-action_time")[: _limit(request)]
)
entries = list(recent_actions_for_user(user_pk, _limit(request)))
body = {"actions": [_serialize_action(e, admin_site, request) for e in entries]}
response = JsonResponse(body, status=200)
response["Cache-Control"] = "no-store"
Expand Down
16 changes: 16 additions & 0 deletions django_admin_react/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

- :func:`object_log_entries` — the ``LogEntry`` queryset for one object,
newest-first, with the acting user pre-fetched.
- :func:`recent_actions_for_user` — the most recent ``LogEntry`` rows for
one user (the index "Recent actions" panel), newest-first.
"""

from __future__ import annotations
Expand All @@ -40,3 +42,17 @@ def object_log_entries(obj: Model) -> QuerySet[LogEntry]:
.select_related("user")
.order_by("-action_time")
)


def recent_actions_for_user(user_pk: str | int, limit: int) -> QuerySet[LogEntry]:
"""Return the most recent ``LogEntry`` rows for one user, newest first.

The user-scoped counterpart of :func:`object_log_entries`: filtered by
the acting user and capped at ``limit`` — exactly how Django's admin
index "Recent actions" panel reads the log
(``LogEntry.objects.filter(user=...)``). Same get_queryset-rule
rationale as the module docstring: LogEntry is a framework audit
table, not a consumer model, so it is read directly here (outside
``api/``) rather than via ``ModelAdmin.get_queryset``.
"""
return LogEntry.objects.filter(user__pk=user_pk).order_by("-action_time")[:limit]
Loading