Skip to content Skip to sidebar Skip to footer

Is There A 'DetailView' In Django Admin?

I know there is a change/update view in Django admin but is there any detail view that just lists out the record's attributes? Kind of like the DetailView in the Django app? Or doe

Solution 1:

I too was investigating this recently.

One approach that works is to create a custom ModelAdmin with a detail_view method that forwards the call to ModelAdmin's changeform_view() method. Then this view is added to the urls list via overriding ModelAdmin.get_urls().

Then, in this method set a class attribute, say __detail_view to True. Then override has_change_permission() method, which returns False, if __detail_view is detected and set to True. This will cause AdminSite to render the fields in readonly mode (using the AdminReadonlyField wrapper fields) instead of the standard AdminField objects.

You can also change the change_form_template to a custom template for detail_view to accommodate custom rendering for detail views.

class CustomModelAdmin(admin.ModelAdmin):
  def has_change_permission(self, request, obj=None):
    if getattr(self, '__detail_view', None):
       return False
    return super().has_change_permission(request, obj)

  def detail_view(self, request, object_id, form_url='', extra_context=None):
    setattr(self, '__detail_view', True)
    # Custom template for detail view
    org_change_form_template = self.change_form_template
    self.change_form_template = self.detail_view_template or self.change_form_template
    ret = self.changeform_view(request, object_id, form_url, extra_context)
    self.change_form_template = org_change_form_template
    delattr(self, '__detail_view')
    return ret

  def get_urls(self):
    urls = super().get_urls()
    # add detail-view for the object
    from django.urls import path

    def wrap(view):
        def wrapper(*args, **kwargs):
            return self.admin_site.admin_view(view)(*args, **kwargs)
        wrapper.model_admin = self
        return update_wrapper(wrapper, view)

    info = self.model._meta.app_label, self.model._meta.model_name
    # Replace the backwards compatibility (Django<1.9) change view
    # for the detail view.
    urls[len(urls)-1] = path('<path:object_id>/', wrap(self.detail_view), name='%s_%s_detail' % info)
    return urls

I haven't tried the custom template approach, but using the __detail_view object attribute to force readonly rending seems to work.

The default change_form_template still shows the delete button at the bottom, which is okay I guess. But it needs another button to actually take you to the real change page where the object can be changed. Again template customization is the way to go here. Hint: look at {% submit_row %} in admin templates and model a custom inclusion template tag that displays the Change button, if the user has change permission. Take note to call the has_change_permission() here to get the real permission before setting the __detail_view attribute.

Not sure if there are other implications for doing it this way, but it ought to work.

HTH


Post a Comment for "Is There A 'DetailView' In Django Admin?"