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

问题描述

我已经为我的模型定义了一个自定义管理操作,它可以按预期完美运行.我还查看了在 SO 上向管理员更改表单页面添加按钮的多种方法.我缺少的唯一步骤是如何使更改表单页面中的按钮使用当前对象执行我的自定义管理操作?

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 the admin change form page here on SO. The only step that I am missing is how do I make a button in the 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 the 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.

注意:如果按钮位于更改表单的底部,Save 按钮旁边,而不是位于顶部 History 这不是很明显.

NOTE: It would be preferable 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.

查看下面的答案 by Remi 为解决方案.为了使其正常工作,需要进行以下更正:

See the answer below 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)

  • 新的包含标签 custom_submit_row 应该放在 templatetags 中而不是 admin 中(参见 自定义模板标签的文档)

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

    这是您可能会浪费一些时间的疏忽.在 change_form.html 中,您不仅需要更改建议的行:

    This is the oversight you could lose 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.

    推荐答案

    你可以看看 change_form_template 并将其设置为您的自定义模板并覆盖 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)
    

    site-packages/django/contrib/admin/templates/change_form.html 复制 change_form.html 并编辑第 40 行

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

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

     {% 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 a lot of code, but mostly copy/paste. Hope that helps.

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

  • 07-05 00:44