Search code examples
pythonpython-3.xdjangodjango-templatesdjango-admin

Cannot hide "Save and add another" button in Django Admin


I would like to hide all the "Save" buttons in Django's Admin's Change Form, for a specific model, when certain conditions are met. Therefore, I override the changeform_view method in the relevant ModelAdmin, like so:

def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
    extra_context = extra_context or {}
    obj = collection_management_MammalianLine.objects.get(pk=object_id)
    if obj:
        if not (request.user.is_superuser or request.user.groups.filter(name='Lab manager').exists() or request.user == obj.created_by):
            extra_context['show_save'] = False
            extra_context['show_save_and_continue'] = False
            extra_context['show_save_and_add_another'] = False
        else:
            pass
    else:
        pass
    return super(MammalianLinePage, self).changeform_view(request, object_id, extra_context=extra_context)

With this code, I can successfully hide the "Save" and "Save and continue" buttons, but not the "Save and add another" one. I can see that submit_line.html contains the following three lines:

{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}

My question is: why can I hide the "Save" and "Save and continue" buttons, but not the "Save and add another" one? Even though the relevant templatetag (show_save_and_continue) is in the template.


Solution

  • The other keys are checked for in the passed context except show_save_and_continue. Django always sets this directly.

    'show_save_and_add_another': (
            context['has_add_permission'] and not is_popup and
            (not save_as or context['add'])
        ),
    

    You can patch the submit_row template tag function to first check the context dictionary for show_save_and_add_another.

    @register.inclusion_tag('admin/submit_line.html', takes_context=True)
    def submit_row(context):
        """
        Display the row of buttons for delete and save.
        """
        change = context['change']
        is_popup = context['is_popup']
        save_as = context['save_as']
        show_save = context.get('show_save', True)
        show_save_and_continue = context.get('show_save_and_continue', True)
        show_save_and_add_another = context.get('show_save_and_add_another', False)
        ctx = Context(context)
        ctx.update({
            'show_delete_link': (
                not is_popup and context['has_delete_permission'] and
                change and context.get('show_delete', True)
            ),
            'show_save_as_new': not is_popup and change and save_as,
            'show_save_and_add_another': (
                context.get('show_save_and_add_another', None) or
                (context['has_add_permission'] and not is_popup and
                (not save_as or context['add']))
            ),
            'show_save_and_continue': not is_popup and context['has_change_permission'] and show_save_and_continue,
            'show_save': show_save,
        })
        return ctx
    

    Edit

    Steps to patch the "admin/submit_line.html" inclusion tag

    1. Create a templatetags folder at the same level of models.py and views.py

    2. Create __init__.py in the templatetags folder

    3. Copy django/contrib/admin/templatetags/admin_modify.py to templatetags/admin_modify.py.

    4. Overwrite submit_row function definition with the one above.

    Note that this is applicable for Django 2.0 and below.

    For recent Django versions, find a context mix that allows this expression to be False.e.g.

    has_add_permission and not is_popup and
    (not save_as or add) and can_save
    

    See values for the names used in the above expression.