如何在自定义React后台面板中复用Django Admin的Recent Actions日志数据
嗨,我刚好碰到过和你一样的需求,其实Django Admin里的Recent Actions组件,底层是用了Django内置的django.contrib.admin.models.LogEntry模型——这个模型专门存储所有后台的操作日志,包括用户、操作类型、目标对象、操作时间这些核心信息,完全能满足你要的「全局通用日志列表」需求,比django-simple-history更贴合你的场景(毕竟simple-history是针对单个模型的历史追踪)。
下面是一步步实现的方法:
1. 先搞懂LogEntry模型的核心字段
先给你梳理下这个模型里最有用的几个字段,方便后面序列化数据:
user:关联到执行操作的用户(ForeignKey到auth.User)action_time:操作发生的具体时间content_type:关联到被操作的模型(ForeignKey到contenttypes.ContentType)object_id:被操作对象的ID(字符串类型)object_repr:被操作对象的显示名称(就是模型__str__方法返回的内容)action_flag:操作类型(1=新增,2=修改,3=删除)change_message:操作的备注信息(Django 1.9+是JSON格式,会记录修改了哪些字段)
2. 用Django REST Framework创建API接口
要把这些数据传给React,最方便的是用DRF(Django REST Framework)来写API。如果你还没装DRF,先执行安装命令:
pip install djangorestframework
然后把rest_framework加到项目的INSTALLED_APPS里。
2.1 编写序列化器
在你的app里创建一个serializers.py,把LogEntry模型及关联字段序列化:
from django.contrib.admin.models import LogEntry, ContentType from django.contrib.auth.models import User from rest_framework import serializers class ContentTypeSerializer(serializers.ModelSerializer): class Meta: model = ContentType fields = ['app_label', 'model'] class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'username', 'email'] class LogEntrySerializer(serializers.ModelSerializer): user = UserSerializer(read_only=True) content_type = ContentTypeSerializer(read_only=True) action_type = serializers.SerializerMethodField() class Meta: model = LogEntry fields = [ 'id', 'user', 'action_time', 'content_type', 'object_id', 'object_repr', 'action_type', 'change_message' ] def get_action_type(self, obj): # 把数字类型的action_flag转成易读的操作名称 action_map = { 1: '新增', 2: '修改', 3: '删除' } return action_map.get(obj.action_flag, '未知操作')
这里我们把关联的user和content_type也序列化出来,还加了一个action_type字段,把数字标识转换成友好的中文操作名,方便React端直接显示。
2.2 编写API视图
接着在views.py里创建列表视图,同时做好权限控制:
from django.contrib.admin.models import LogEntry from rest_framework.generics import ListAPIView from rest_framework.permissions import IsAdminUser from .serializers import LogEntrySerializer class AdminLogEntryListView(ListAPIView): serializer_class = LogEntrySerializer permission_classes = [IsAdminUser] # 只有管理员能访问,和Django Admin权限保持一致 queryset = LogEntry.objects.all().order_by('-action_time') # 按时间倒序,最新操作在前 # 如果你想限制只显示最近N条,比如最近50条,可以修改queryset: # queryset = LogEntry.objects.all().order_by('-action_time')[:50]
用IsAdminUser权限类,确保只有能访问Django Admin的用户才能调用这个API,和后台权限体系保持一致。如果需要更细粒度的权限,也可以自定义权限类。
2.3 配置API路由
在项目的urls.py里添加API的访问路径:
from django.urls import path from .views import AdminLogEntryListView urlpatterns = [ # 其他URL路由... path('api/admin-log-entries/', AdminLogEntryListView.as_view(), name='admin-log-entries'), ]
3. React端调用API并渲染日志
现在你可以在React项目里,用fetch或者axios调用这个API,比如用axios的示例:
import React, { useState, useEffect } from 'react'; import axios from 'axios'; const AdminRecentActions = () => { const [logEntries, setLogEntries] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchLogEntries = async () => { try { // 注意:如果用Django session认证,要带上withCredentials确保cookie传递 const response = await axios.get('/api/admin-log-entries/', { withCredentials: true, }); setLogEntries(response.data); } catch (error) { console.error('获取日志失败:', error); } finally { setLoading(false); } }; fetchLogEntries(); }, []); // 解析change_message(Django 1.9+为JSON格式) const parseChangeMessage = (message) => { try { const parsed = JSON.parse(message); return parsed.map(item => item.field).join(', '); } catch (e) { return message; } }; if (loading) { return <div>加载操作日志中...</div>; } return ( <div className="recent-actions-container"> <h3>最近操作日志</h3> <ul className="log-list"> {logEntries.map(entry => ( <li key={entry.id} className="log-item"> <p className="log-header"> <strong>{entry.user.username}</strong> 于 {new Date(entry.action_time).toLocaleString()} 对 <em>{entry.content_type.model}</em> 执行了 <strong className={`action-${entry.action_type}`}>{entry.action_type}</strong> </p> <p className="log-object">对象:{entry.object_repr}</p> {entry.change_message && ( <p className="log-change">修改字段:{parseChangeMessage(entry.change_message)}</p> )} </li> ))} </ul> </div> ); }; export default AdminRecentActions;
这里要注意认证的问题:如果你的Django后台用session认证,React端调用时要加withCredentials: true;如果用JWT认证,要在请求头里带上Authorization: Bearer <token>。
额外的实用小技巧
- 按模型过滤日志:如果只想显示某个模型的操作记录,可以在API视图的
queryset里加过滤,比如LogEntry.objects.filter(content_type__model='article')。 - 分页处理:如果日志量很大,建议给API加上分页,用DRF的
PageNumberPagination组件,避免一次加载太多数据。 - 自定义日志内容:如果需要在日志里加入更多自定义信息,可以通过重写模型的
save方法或者使用信号,手动向LogEntry添加记录。
备注:内容来源于stack exchange,提问作者Adeel Ahmed

