django-simple-history中ManyToManyField的历史

6 投票
2 回答
2751 浏览
提问于 2025-04-18 09:42

简单来说,我需要记录我模型中多对多字段的更改历史。

我从这个链接可以看到:https://github.com/Kyruus/django-simple-history/commit/5ba8d2b4d72819f154a11f297796e6a2bb7172bf,多对多字段是被支持的。但是每当我对多对多字段进行更改时,历史记录中的内容也会一起改变,就好像从来没有被更改过一样。我对django和python还很陌生,可能我漏掉了什么。

我的models.py文件内容:

from django.db import models
from simple_history.models import HistoricalRecords

class Student(models.Model):
  studentname = models.CharField(max_length=50, verbose_name='Name')

class ClassRoom(models.Model):
  classname = models.CharField(max_length=50, verbose_name='Name')
  students = models.ManyToManyField(Student)
  history = HistoricalRecords()

我的admin.py文件内容:

from django.contrib import admin
from school.models import Student, ClassRoom
from simple_history.admin import SimpleHistoryAdmin

class StudentAdmin(SimpleHistoryAdmin):
  list_display = ('studentname',)

class ClassRoomAdmin(SimpleHistoryAdmin):
  list_display = ('classname',)

admin.site.register(Student,StudentAdmin)
admin.site.register(ClassRoom, ClassRoomAdmin)

我通过以下方式安装了django-simple-history:

>pip install django-simple-history

2 个回答

0

因为 m2m_fields 在标准版本中其实是不可用的,这里有一个使用 django-simple-history 包的替代解决方案。

你可以手动创建多对多的表,而不是使用 Django 的添加和删除方法,你只需要创建和删除关系。如果我们用一个例子来看,会是这样的:

class Student(models.Model):
  studentname = models.CharField(max_length=50, verbose_name='Name')

class ClassRoom(models.Model):
  classname = models.CharField(max_length=50, verbose_name='Name')
  history = HistoricalRecords()

class StudentClassRooms(models.Model):
    student = models.ForeignKey(Student)
    classroom = models.ForeignKey(ClassRoom)
    history = HistoricalRecords()

如果你现在使用:

StudentClassRooms.objects.create(student=student, classroom=classroom) 来代替 classroom.students.add(student),并且用 delete() 来代替 classroom.students.remove(student),那么你就可以在历史表中追踪到所有的记录,同时也能保持同样的多对多关系表。

6

这是一个很久以前提出的问题,现在可能已经不太相关了。不过从我查看的这个项目的代码来看,ClassRoom模型的最后一行应该改成下面这样:

history = HistoricalRecords(m2m_fields=['students'])

撰写回答