Revert objects on site instead of admin using djan

2019-08-21 02:23发布

问题:

I have employed django simple history package on the admin site to be able to track and revert to previous versions of the object of the model. I am designing a web form that allows users to change instances of the model object using model form on django and would like to allow the users to view and revert to previous versions. Also to allow them to see what are the changes compared to the current version.

With the code below I am able to get the list of historical records on my template under histoire.

class CompanyDetailView(LoginRequiredMixin,generic.DetailView):
    model = Company

    def get_context_data(self, **kwargs):
         context = super(CompanyDetailView, self).get_context_data(**kwargs)
         company_instance = self.object
         context['histoire'] = company_instance.history.all()
         return context

In my template,

<p>
    Previous versions:
    {% for item in histoire %}
      <li>
        {{ item }} submitted by {{ item.history_user }}  {{
         item.history_object }}
      </li>
      {% endfor %}

</p>

But ideally I want item.history_object to be a link that users can view the previous object and be able to revert if desired.

回答1:

I did something similar by adding HistoricForm to my model forms.

class MyModelForm(HistoricForm, ModelForm):
     ...

HistoricForm takes and extra history_id kwarg. If history_id is provided HistoricForm swaps the ModelForm instance with the historic_instance (what your instance looked like at the time of history_id). This way your form will show the historic version of your object.

class HistoricForm(object):
    def __init__(self, *args, **kwargs):
        self.history_id = kwargs.pop('history_id', None)
        instance = kwargs.get('instance')
        if instance and self.history_id:
            kwargs['instance'] = self.get_historic_instance(instance)

        super(HistoricForm, self).__init__(*args, **kwargs)

    def get_historic_instance(self, instance):
        model = self._meta.model
        queryset = getattr(model, 'history').model.objects
        historic_instance = queryset.get(**{
            model._meta.pk.attname: instance.pk,
            'history_id': self.history_id,
        }).instance
        return historic_instance

If history_id is not provided the ModelForm works as usual.

You can revert by showing the historic instance and save (this way you will post your historic data).