如何为Django创建指定格式的操作日志系统及公共API
Alright, let's break down each requirement with practical code implementations tailored to your Django project structure:
1. Build Logging Functionality with Custom Entry Format
We'll tie this directly to your existing OperatorLog model, ensuring every log entry follows the specified "message. User: 操作人员姓名" format via a reusable helper function.
First, assume your OperatorLog model includes fields like user (ForeignKey to auth.User), activity_type, message, and timestamp—adjust code snippets if your model has different fields.
2. Public API for Registering Events (activity/api.py)
This is the core utility other apps will use to log actions. We'll also make your activity constants accessible here:
# activity/api.py from django.contrib.auth.models import User from .models import OperatorLog from .constants import ACTIVITY_TYPES # Import your existing activity type list # Re-export constants so other apps can import directly from this file ACTIVITY_TYPES = ACTIVITY_TYPES def log_operator_action(user: User, activity_type: str, message: str) -> OperatorLog: """ Public API to create an operator activity log entry. Automatically formats the message to include the user's name. """ # Optional: Validate activity type against your constants if activity_type not in ACTIVITY_TYPES: raise ValueError(f"Invalid activity type. Allowed values: {ACTIVITY_TYPES}") # Apply the required message format formatted_message = f"{message}. User: {user.get_full_name() or user.username}" # Create and save the log entry log_entry = OperatorLog.objects.create( user=user, activity_type=activity_type, message=formatted_message ) return log_entry
Other apps can use this API like so:
# Example in another app's view/service from activity.api import log_operator_action, ACTIVITY_TYPES # Log an action when a user edits an item log_operator_action( user=request.user, activity_type=ACTIVITY_TYPES["EDIT_ITEM"], # Match your constant's structure message="Updated product details for item #456" )
3. API Endpoint to Retrieve Formatted Activity Logs
Using Django REST Framework (DRF), create a view to return all formatted log records:
# activity/api.py (continued) from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAdminUser # Adjust permissions as needed from .serializers import OperatorLogSerializer class OperatorLogListView(APIView): permission_classes = [IsAdminUser] # Restrict access to admins if required def get(self, request): # Fetch logs ordered by most recent first logs = OperatorLog.objects.all().order_by("-timestamp") serializer = OperatorLogSerializer(logs, many=True) return Response(serializer.data)
Add this endpoint to your app's URLs:
# activity/urls.py from django.urls import path from .api import OperatorLogListView urlpatterns = [ path("activity-logs/", OperatorLogListView.as_view(), name="operator-logs"), ]
Create a serializer to format the response (activity/serializers.py):
from rest_framework import serializers from .models import OperatorLog class OperatorLogSerializer(serializers.ModelSerializer): class Meta: model = OperatorLog fields = ["id", "message", "timestamp", "user"] # Include fields you want to expose # Optional: If you need to reformat the message here instead of at creation # formatted_message = serializers.SerializerMethodField() # def get_formatted_message(self, obj): # return f"{obj.message}. User: {obj.user.get_full_name() or obj.user.username}"
4. Make Activity Types Accessible via api.py
As shown earlier, re-exporting the ACTIVITY_TYPES constant from constants.py in api.py lets other apps import everything they need from a single source:
# activity/api.py from .constants import ACTIVITY_TYPES ACTIVITY_TYPES = ACTIVITY_TYPES
Other apps can now access constants like:
from activity.api import ACTIVITY_TYPES
Quick Notes:
- Adjust permissions in the log endpoint to match your project's needs (e.g., allow users to view their own logs).
- Add error handling in
log_operator_action(e.g., handle anonymous users if needed). - If your
OperatorLogmodel lacks auserfield, add a ForeignKey toauth.Userfirst.
内容的提问来源于stack exchange,提问作者Alenorze

