5

Story short, I need to save in the history the changes made on a Many-To-Many fields of one of my models.

I can see from: https://github.com/Kyruus/django-simple-history/commit/5ba8d2b4d72819f154a11f297796e6a2bb7172bf that the M2M is supported. However whenever I make a change on a M2M field it changes as well in all the history, as if never has been changed. I'm new to django and python so maybe I'm missing something.

My 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()

My 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)

I installed the django-simple-history by:

>pip install django-simple-history
EricPb
  • 560
  • 1
  • 8
  • 21

2 Answers2

6

This is an old open question, and might be irrelevant by now, but from looking into the code of the project in question, it seems like the last line on the ClassRoom model should be changed to

history = HistoricalRecords(m2m_fields=['students'])
ShacharSh
  • 500
  • 3
  • 15
  • Thanks @ShacharSh but I finally decided to go for django-reversion instead. – EricPb Apr 29 '15 at 01:35
  • Thanks for sharing. If you happen to check my answer and it does solve the problem for you, I would appreciate if you could mark my answer as helpful – ShacharSh Apr 29 '15 at 07:44
  • ShacharSh, I believe you are right. Though if I look though the code changes in Kyruus' fork, I see no changes in the admin view, so that might be complicating things. – Wim Feijen Apr 16 '17 at 07:26
  • @EricPb I have some difficulties in finding the right code for django-reversion. Is it possible to post your code implementation here as an answer to your question? That would be very helpful, thanks! – Wim Feijen Apr 28 '17 at 13:53
0

Since m2m_fields is actually not available in the standard branch, here's an alternative solution using the django-simple-history package.

You can manually create the many to many table and instead of using djangos add and remove you simply create and delete the relations. If you look at it with an example we would have:

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()

if you now use:

StudentClassRooms.objects.create(student=student, classroom=classroom) instead of classroom.students.add(student) and delete() instead of classroom.student.remove(student) you will have everything tracked in a history table and the same many to many table.

fsulser
  • 853
  • 2
  • 10
  • 34