jazzband / django-simple-history

Store model history and view/revert changes from admin site.
https://django-simple-history.readthedocs.org
BSD 3-Clause "New" or "Revised" License
2.18k stars 476 forks source link

Incorrect rendering of history entry (with editable fields) if changing is disallowed #1362

Open stefan6419846 opened 2 months ago

stefan6419846 commented 2 months ago

Describe the bug

Opening a specific entry from the history shows the fields as editable, although there are no change permissions and there is no save button.

To Reproduce

Consider an admin page defined like this:

from django.contrib import admin
from .models import Package
from simple_history.admin import SimpleHistoryAdmin

class ReadonlyHistoryAdmin(SimpleHistoryAdmin):
    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

admin.site.register(Package, ReadonlyHistoryAdmin)

If relevant: SIMPLE_HISTORY_REVERT_DISABLED = True is set.

Steps to reproduce the behavior:

  1. Go to http://localhost:8000/admin/app_name/package/
  2. Open a package: http://localhost:8000/admin/app_name/package/4/change/
  3. Open the history: http://localhost:8000/admin/app_name/package/4/history/
  4. Open a specific version in history: http://localhost:8000/admin/app_name/package/4/history/6/

Expected behavior

The specific version is shown as read-only form and does not allow saving.

Screenshots

Regular view:

ksnip_20240627-150348

Historic view:

ksnip_20240627-150425

Environment

Additional context

Additionally, it seems like the rendering of at least the heading is slightly different.

cfdbwrbq commented 1 month ago

also if class looks something like this

class SomeClass(models.Model):
    name=models.CharField(editable=False)
    ...
    def __str__(self):
        return self.name

in admin interface history link crashes with error

TypeError at /admin/model/1/history/__str__ returned non-string (type of NoneType)

but the name value of object definitely exists. and if remove __str__ function - OK, history is showing...