AuditLogMiddleware runs on every response and writes one AuditLog row containing the authenticated user, the HTTP method and path, the request body, and the response status code and body.
How audit logging works
The middleware inapi/middleware.py intercepts every response:
- Reads
request.user— storesnullfor unauthenticated requests. - Decodes
request.bodyas JSON when possible; falls back to raw text. - Decodes
response.contentas JSON when possible. - Creates one
AuditLogrow withaction = '<METHOD> <path>'.
purchase_orders/audit.py write structured JSON entries to logs/audit.log via the purchase_audit logger for every create, update, and delete on PurchaseOrders and Payments models.
Endpoints
GET /api/audit_log/
Returns a paginated list of all audit log entries, ordered bytimestamp descending.
Example request
cURL
Filter entries by user ID. Returns only entries where
user matches the given ID.Filter by action string. The value stored is
'<METHOD> <path>', for example POST /api/payments/create/. Supports partial matching depending on the configured queryset filter.Filter by model name. The middleware sets this to
'API Request' for HTTP-level entries. Signal-based entries use the Django model name (e.g. PurchaseOrders, Payments).Field to sort by. Entries default to newest first (
-timestamp).Auto-incremented primary key for the log entry.
ISO 8601 datetime when the entry was created. Automatically set on insert.
Foreign key to the Django
auth_user table. null for unauthenticated requests.Description of the action performed. For HTTP-level entries the format is
'<METHOD> <path>', e.g. GET /api/payments/methods/.Name of the model or resource affected. Set to
'API Request' by the middleware for all HTTP traffic.Primary key of the affected record when the action targets a specific object.
null for list operations or middleware-generated entries.Free-text field containing additional context. The middleware stores the full request body, response HTTP status code, and response body here.
GET /api/audit_log//
Retrieve a single audit log entry by its primary key.Primary key of the audit log entry.
Log file output
In addition to the database table, the logging subsystem (api/logging_config.py) writes to rotating log files on disk:
| Logger name | File | Max size | Backups |
|---|---|---|---|
audit | logs/audit.log | 20 MB | 10 |
purchase_audit | structured JSON via audit_logger | — | — |
payments | logs/payments.log | 10 MB | 5 |
purchase_orders | logs/purchase_orders.log | 10 MB | 5 |
Version tracking
The platform uses django-reversion for model-level version tracking. This provides a complete change history for any model registered withreversion, allowing admins to view diffs between versions and revert records to a previous state through the Django admin interface.
Admin UI
TheAdmin > Logs page in the frontend (src/pages/Admin/Logs.jsx) fetches from /api/admin/audit-logs/ and displays a table with the id, user, action, and timestamp columns. This view is accessible only to authenticated admin users.