Mikhail
Mikhail

Reputation: 71

Django-admin list_editable enable/disable on the fly (edit/view mode check)

I want to change edit/view mode of the page by button (or something like it). Edit mode is equal to list_editable specified in EntityModelAdmin body. View mode is equal to empty list_editable.

@admin.register(models.EntityModel)
class EntityModelAdmin(admin.ModelAdmin):
    list_display = ('name', 'barcode', 'short_code', )
    list_editable = ('barcode', 'short_code', )

How to achieve this? Seems I should override some class/function to consider the state of mode trigger.

Also it will be good to do the same (all fields is read-only) with add/change page of Entity instance.

Upvotes: 1

Views: 2411

Answers (2)

Mikhail
Mikhail

Reputation: 71

As for me it's better to override changelist_view method of admin.ModelAdmin:

class EntityModelAdmin(admin.ModelAdmin):
    list_display = ('name', 'barcode', 'short_code', )
    list_editable = ('barcode', 'short_code', )

    @csrf_protect_m
    def changelist_view(self, request, extra_context=None):
        """
        The 'change list' admin view for this model.
        Overrided only for add support of edit/view mode switcher.
        """
        ...parent code...
        try:
            cl = ChangeList(request, ...parent code...)

            # Customization for view/edit mode support
            if 'edit_mode' not in request.COOKIES:
                cl.list_editable = ()
        ...parent code...

Possible it's better to override another method. Not sure if it possible to override only some part of pretty big changelist_view method without copying most of all code as is (...parent code...).

Button switcher can be like this:

{% load myapp_various_tags %}  {# load get_item tag for dictionary #}

    <div id="mode">
        <div class="mode_item edit_mode {% if request.COOKIES|get_item:'edit_mode' %}selected{% endif %}" onclick="$.cookie('edit_mode', '1', { path: '/', expires: 30 }); location.reload(true);">
            <div class="header_icon"></div>
            <div class="header_text">{% trans "edit" %}</div>
        </div>
        <div class="mode_item view_mode {% if not request.COOKIES|get_item:'edit_mode' %}selected{% endif %}" onclick="$.cookie('edit_mode', null, { path: '/', expires: -1 }); location.reload(true);">
            <div class="header_icon"></div>
            <div class="header_text">{% trans "view" %}</div>
        </div>
    </div>

Where myapp_various_tags.py is:

from django.template.defaulttags import register
@register.filter
def get_item(dictionary, key):
    return dictionary.get(key)

Possible it's not "true way" but all of this is just works.

Also it will be good to do the same (all fields is read-only) with add/change page of Entity instance.

django admin: separate read-only view and change view

Upvotes: 1

catavaran
catavaran

Reputation: 45565

Create proxy model for the EntityModel:

class ProxyEntityModel(EntityModel):
    class Meta:
        proxy = True

And then the separate ModelAdmin for it:

class ProxyEntityModelAdmin(admin.ModelAdmin):
    list_display = ('name', 'barcode', )
    list_editable = ('barcode', )

Upvotes: 0

Related Questions