You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义React后台面板中复用Django Admin的Recent Actions日志数据

如何在自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 08:09:51