我想在特定模型中隐藏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)
使用此代码,我可以成功隐藏“保存”和“保存并继续”按钮,但不能隐藏“保存并添加另一个”按钮。我可以看到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 %}
我的问题是:为什么我可以隐藏“保存”和“保存并继续”按钮,而不是“保存并添加另一个”按钮?即使相关的模板标签(show_save_and_continue)在模板中。
答案 0 :(得分:1)
除了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'])
),
您可以修补submit_row
模板标记功能,首先查看context
的{{1}}字典。
show_save_and_add_another
修改
修补&#34; admin / submit_line.html&#34;的步骤包含标记
在@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
和templatetags
models.py
文件夹
在views.py
文件夹
__init__.py
将django/contrib/admin/templatetags/admin_modify.py复制到templatetags
。
使用上面的一个覆盖templatetags/admin_modify.py
函数定义。
请注意这适用于 Django 2.0 及以下。
对于最近的Django版本,找到允许此表达式为submit_row
的上下文混合。例如
False
答案 1 :(得分:1)
我有另一种隐藏“保存并添加其他”按钮的方法。
在form.py
class TestForm(forms.ModelForm):
class Media:
js = ('admin/yourjsfile.js',)
在yourjsfile.js
(function($) {
'use strict';
$(document).ready(function() {
// hide the "Save and add another" button
$("input[name='_addanother']").attr('type','hidden');
});
})(django.jQuery);
我有同样的问题隐藏该按钮。 我在Django 1.11中测试过它确实有效,但我认为有更好的方法可以实现它。
答案 2 :(得分:1)
一些其他选项:
在save_as=True
上设置ModelAdmin
。如docs中所述,这将用“ 另存为新”按钮替换“ 保存并添加另一个”按钮。据我所知,这可能并不适合所有情况,但这是最简单的解决方案。
在您的has_add_permission
上为ModelAdmin
方法应用猴子补丁,因此在调用False
(或super().change_view
的过程中,它返回changeform_view
)。
覆盖TemplateResponse.content
(docs),以从HTML中简单隐藏(或删除)包含按钮的submit-row
元素。
最简单的选择是在save_as=True
上设置ModelAdmin
。这会将“ 保存并添加另一个”按钮替换为“ 另存为新”按钮。因此,假设其他保存按钮已被禁用,则对当前对象所做的任何更改都只能保存为新对象。当前对象将保持不变。
基本实现:
class MyModelAdmin(ModelAdmin):
save_as = True
# your other code here, such as the extended changeform_view
submit_line.html模板显示了哪些上下文变量用于显示/隐藏保存和删除按钮。这些上下文变量中的大多数可以通过extra_context
(或changeform_view
)中的change_view
进行设置。但是,正如OP所示,我们不能简单地以这种方式覆盖show_save_and_add_another
。
如@Oluwafemi-Sule的回答所指出,
在admin_modify.py中设置了show_save_and_add_another
,这为submit_line.html创建了上下文。
在仔细检查源代码时,很容易覆盖has_add_permission
上下文变量,因为它确定了show_save_and_add_another
的值。但是,仅将has_add_permission=False
添加到extra_context
在Django < 2.1
中是行不通的,因为通过ModelAdmin.render_change_form方法将撤消更改。
幸运的是,我们可以使用has_add_permission
中的monkey patch来欺骗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
如果将OP(source)中的change_view
替换为changeform_view
,这也将起作用。
注意:很明显,只有在has_add_permission=False
不影响更改视图中的其他事物的情况下,才能使用此选项。
基于此example from the docs,还可以从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
如前所述,我们也可以完全删除submit-row
部分,但这需要更多工作。
这比选项2简单,但更脆弱。
答案 3 :(得分:0)
您可以覆盖 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)
答案 4 :(得分:0)
我建议(更改djvg答案的选项3),使用正则表达式删除此html输入元素,如以下示例所示:
class MyModelAdmin(admin.ModelAdmin):
def add_view(self, request, form_url='', extra_context=None):
template_response = super(MyModelAdmin, self).add_view(
request, form_url=form_url, extra_context=extra_context)
# POST request won't have html response
if request.method == 'GET':
# removing Save and add another button: with regex
template_response.content = re.sub("<input.*?_addanother.*?(/>|>)", "", template_response.rendered_content)
return template_response
_addanother
是此html元素的ID
答案 5 :(得分:0)
如果没有人反对,那么我会发布我的小技巧。
可以将其插入任何地方,并可以从settings
文件中调用(最好在最后)。
# Hide "save_and_add_another" button
from django.contrib.admin.templatetags import admin_modify
submit_row = admin_modify.submit_row
def submit_row_custom(context):
ctx = submit_row(context)
ctx['show_save_and_add_another'] = False
return ctx
admin_modify.submit_row = submit_row_custom