无法在 Django Admin 中隐藏“保存并添加另一个”按钮

Nic*_*lio 4 django django-templates

当满足某些条件时,对于特定模型,我想隐藏 Django 管理员更改表单中的所有“保存”按钮。因此,我覆盖了changeform_view相关的方法ModelAdmin,如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

使用此代码,我可以成功隐藏“保存”和“保存并继续”按钮,但不能隐藏“保存并添加另一个”按钮。我可以看到submit_line.html包含以下三行

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么我可以隐藏“保存”和“保存并继续”按钮,而不是“保存并添加另一个”按钮?即使相关的模板标签 (show_save_and_continue) 在模板中。

un1*_*n1t 7

您可以覆盖ModelAdmin子类中的render_change_form方法。在此方法中obj可用作参数,您可以检查某些条件。

class OrderAdmin(admin.ModelAdmin):

    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
        context.update({
            'show_save': False,
            'show_save_and_continue': False,
            'show_delete': False
        })
        return super().render_change_form(request, context, add, change, form_url, obj)
Run Code Online (Sandbox Code Playgroud)

  • 不删除保存并添加另一个 (4认同)
  • context.update({ 'show_save_and_add_another': False }) 适用于 django 3.1 (4认同)

djv*_*jvg 5

编辑:

从 Django 3.1 开始,原始问题的方法应该可以简单地工作:

...
extra_context['show_save_and_add_another'] = False
...
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此 Django 提交

旧答案:

概括

一些附加选项:

  1. 设置save_as=True在您的ModelAdmin. 如文档中所述,这将用“另存为新”按钮替换“保存并添加另一个”按钮。这可能并不适合所有情况,但据我所知,这是最简单的解决方案。

  2. has_add_permission为您的方法应用猴子补丁ModelAdmin,以便它False在调用super().change_view(或changeform_view) 期间返回。

  3. 覆盖TemplateResponse.content( docs ) 以简单地从 HTML 中隐藏(或删除)submit-row包含按钮的元素。

详情选项1

最简单的选项是save_as=TrueModelAdmin. 这将用“另存为新”按钮替换“保存并添加另一个”按钮。因此,假设其他保存按钮已被禁用,对当前对象所做的任何更改只能保存为新对象。当前对象将保持不变。

基本实现:

class MyModelAdmin(ModelAdmin):
    save_as = True

    # your other code here, such as the extended changeform_view 
Run Code Online (Sandbox Code Playgroud)

详情选项2

Submit_line.html模板显示了哪些上下文变量用于显示/隐藏保存和删除按钮。extra_context大多数上下文变量可以通过in changeform_view(或)设置change_view。然而,正如OP所示,我们不能简单地show_save_and_add_another以这种方式覆盖。

正如@Oluwafemi-Sule的答案 中所指出的,在admin_modify.pyshow_save_and_add_another中设置,它为Submit_line.html创建上下文。

仔细检查源代码后,您很容易会覆盖has_add_permission上下文变量,因为它决定了 的值show_save_and_add_another。但是,简单地添加has_add_permission=Falseextra_context在 中不起作用Django < 2.1,因为更改将被ModelAdmin.render_change_form方法撤消。

has_add_permission幸运的是,我们可以简单地欺骗 Django,使其认为是这样,而不是覆盖模板或修补模板标签,在 中False使用猴子补丁change_view

def change_view(self, request, object_id=None, form_url='', extra_context=None):
    # use extra_context to disable the other save (and/or delete) buttons
    extra_context = dict(show_save=False, show_save_and_continue=False, show_delete=False)
    # get a reference to the original has_add_permission method
    has_add_permission = self.has_add_permission
    # monkey patch: temporarily override has_add_permission so it returns False
    self.has_add_permission = lambda __: False
    # get the TemplateResponse from super (python 3)
    template_response = super().change_view(request, object_id, form_url, extra_context)
    # restore the original has_add_permission (otherwise we cannot add anymore)
    self.has_add_permission = has_add_permission
    # return the result
    return template_response
Run Code Online (Sandbox Code Playgroud)

change_view如果您替换为changeform_viewOP()所使用的,这也适用。

has_add_permission=False注意:显然,只有在不干扰更改视图中的其他内容的情况下才能使用此选项。

详情选项3

根据文档中的这个示例,也可以简单地submit-row从渲染的 HTML 中隐藏(甚至删除) change_view

def change_view(self, request, object_id=None, form_url='',
                extra_context=None):
    # get the default template response
    template_response = super().change_view(request, object_id, form_url,
                                            extra_context)
    # here we simply hide the div that contains the save and delete buttons
    template_response.content = template_response.rendered_content.replace(
        '<div class="submit-row">',
        '<div class="submit-row" style="display: none">')
    return template_response
Run Code Online (Sandbox Code Playgroud)

如前所述,我们也可以submit-row完全删除该部分,但这需要更多的工作。

这比选项 2 更简单,但更脆弱。


Olu*_*ule 2

除了 之外,其他键都会在传递的上下文中进行检查show_save_and_continue。Django总是直接设置它

'show_save_and_add_another': (
        context['has_add_permission'] and not is_popup and
        (not save_as or context['add'])
    ),
Run Code Online (Sandbox Code Playgroud)

您可以修补submit_row模板标签功能以首先检查context字典中的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
Run Code Online (Sandbox Code Playgroud)

编辑

修补“admin/submit_line.html”包含标记的步骤

  1. 创建一个与 和templatetags同一级别的文件夹models.pyviews.py

  2. __init__.pytemplatetags文件夹中创建

  3. 将django/contrib/admin/templatetags/admin_modify.py复制到templatetags/admin_modify.py.

  4. submit_row用上面的函数定义覆盖函数定义。

请注意,这适用于Django 2.0及更低版本。

对于最新的 Django 版本,找到允许此表达式为 的上下文混合False例如

has_add_permission and not is_popup and
(not save_as or add) and can_save
Run Code Online (Sandbox Code Playgroud)

请参阅上述表达式中使用的名称的值