本文介绍了Django:如何将自定义按钮添加到执行管理操作的管理员更改表单页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为我的模型定义了一个自定义的管理操作,按照预期工作完美。我也在这里查看了多种添加按钮到管理员更改表单页面的方法。只有我缺少的一步是如何使更改表单页面中的按钮使用当前对象执行我的自定义管理操作。

I have already defined a custom admin action for my model which works perfectly as expected. I also looked at multiple ways of adding a button to admin change form page here on SO. Only step that I am missing is how to make a button in change form page execute my custom admin action with current object.

目标是允许管理员检查每个对象单独执行操作,无需返回列表视图,选择被检查对象,并从列表中执行操作。

The goal is to allow admin to inspect every object individually and perform an action on them without needing to go back to list view, selecting the inspected object, and executing the action from list.

我的自定义管理操作看起来像这样:

My custom admin action looks like this:

def admin_apply_change(modeladmin, request, queryset):
    # loop over objects in query set and perform action

我假设有一种简单干净的方式在管理员更改表单中调用此操作,其中 queryset 只会包含管理员正在查看的当前打开的对象。

I am assuming there is a simple and clean way of calling this action in admin change form, where the queryset would only contain the currently opened object the admin is looking at.

注意:如果按钮位于更改表单的底部,旁边保存按钮,而不是在历史的顶部,这不是很可见。

NOTE: It would be preferrable if the button is at the bottom of the change form, next to Save button instead of being at top with History which is not very visible.

请参阅的解决方案。为了使其工作,需要进行以下更正:

See the answer by Remi for the solution. In order to make it work the following corrections are needed:

1:在 response_change 的替换中,初始化一些变量缺少:

1: In the override of response_change initialization of some variables is missing:

opts = self.model._meta
pk_value = obj._get_pk_val()
preserved_filters = self.get_preserved_filters(request)

2:新的包含标签 custom_submit_row 应放置在模板标签中,而不是在管理员中(请参阅)

2: New inclusion tag custom_submit_row should be placed in templatetags and not in admin (see docs for custom templatetags)

3:这是您可以放松一些时间的疏忽。在 change_form.html 中,您不仅需要更改建议的行:

3: This is the oversight you could loose some time on. In change_form.html you not only have to change the suggested line:

{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}

,而且底部更重要的一行出现在 submit_row 中:

but also the more important line at the bottom where submit_row appears:

{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}

(它位于 change_form.html 中的javascript块的上方)

(it is located just above the javascript block in change_form.html)

推荐答案

您可以查看,并将其设置为您的自定义模板,并覆盖 response_change 方法:

You could take a look at the change_form_template and set it to a custom template of yours and override the response_change method:

class MyModelAdmin(admin.ModelAdmin):

    # A template for a customized change view:
    change_form_template = 'path/to/your/custom_change_form.html'

    def response_change(self, request, obj):
        opts = self.model._meta
        pk_value = obj._get_pk_val()
        preserved_filters = self.get_preserved_filters(request)

        if "_customaction" in request.POST:
            # handle the action on your obj
            redirect_url = reverse('admin:%s_%s_change' %
                               (opts.app_label, opts.model_name),
                               args=(pk_value,),
                               current_app=self.admin_site.name)
             redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
             return HttpResponseRedirect(redirect_url)
        else:
             return super(MyModelAdmin, self).response_change(request, obj)

复制 change_form.html fr om你的 site-packages / django / contrib / admin / templates / change_form.html 并编辑行44

Copy the change_form.html from your site-packages/django/contrib/admin/templates/change_form.html and edit the line 44

 {% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}

to

 {% if save_on_top %}{% block submit_buttons_top %}{% custom_submit_row %}{% endblock %}{% endif %}

还要检查行:

 {% block submit_buttons_bottom %}{% submit_row %}{% endblock %}

刚刚在javascript块上方。

just above the javascript block.

然后你可以在某个地方注册一个新的包含标签在您的admin.py中或将其添加到模板标签中:

Then you can register a new inclusion tag somewhere in your admin.py or add it to templatetags:

@register.inclusion_tag('path/to/your/custom_submit_line.html', takes_context=True)
def custom_submit_row(context):
    """
    Displays the row of buttons for delete and save.
    """
    opts = context['opts']
    change = context['change']
    is_popup = context['is_popup']
    save_as = context['save_as']
    ctx = {
        'opts': opts,
        '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['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'],
        'is_popup': is_popup,
        'show_save': True,
        'preserved_filters': context.get('preserved_filters'),
    }
    if context.get('original') is not None:
        ctx['original'] = context['original']
    return ctx

内容的 custom_submit_line.html

{% load i18n admin_urls %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
{% if show_delete_link %}
    {% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
    <p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">{% trans "Delete" %}</a></p>
{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% 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 %}

<input type="submit" value="{% trans 'Custom Action' %}"  name="_customaction" />

</div>

这是很多代码,但主要是复制/粘贴。希望有帮助。

It is alot of code, but mostly copy/paste. Hope that helps.

这篇关于Django:如何将自定义按钮添加到执行管理操作的管理员更改表单页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-05 00:43