# -*- coding: UTF-8 -*- from django.db import models from datetime import datetime class FullHistory(models.Model): """ Issues: Unique fields don't work (multiple versions of the same row may need to have the same value) """ date_created = models.DateTimeField(default=datetime.now, editable=False) date_updated = models.DateTimeField(default=datetime.now, editable=False) class Meta: abstract = True ordering = ('date_updated',) def __init__(self, *args, **kwargs): # History classes must end in 'History', others must not. if self.__class__.__name__.endswith('History'): self._history_class = True else: self._history_class = False super(FullHistory, self).__init__(*args, **kwargs) def save(self, *args, **kwargs): if self._history_class: self._save_history_instance() else: self._save_non_history_instance() super(FullHistory, self).save(*args, **kwargs) def _save_history_instance(self): """ Save method for a History object. """ # This updated instance must become a new object, # no updating is possible for history classes self.id = None def _save_non_history_instance(self): """ Save method for a non-History object. """ # Duplicate and reassign parent. for model, field in self._meta.parents.items(): if getattr(self, '%s_id' % field.name) is not None: rel_obj = getattr(self, field.name) rel_obj.id = None rel_obj.save() setattr(self, '%s_id' % field.name, rel_obj.id) # Set the new update time on the non-archived version self.date_updated = datetime.now() def delete(self): # Only delete if this is not a "history" version if not self._history_class: self.save() super(FullHistory, self).delete()