web-dev-qa-db-ja.com

Django:管理アクションを実行する管理変更フォームページにカスタムボタンを追加する方法

期待どおりに完全に機能するモデルのカスタム管理アクションをすでに定義しています。また、ここでSOのフォーム変更ページを管理するためのボタンを追加する複数の方法を確認しました。私が欠けている唯一のステップは、変更フォームページのボタンに、現在のオブジェクトを使用してカスタム管理アクションを実行させる方法です。

目標は、管理者がすべてのオブジェクトを個別に検査し、リストビューに戻って検査されたオブジェクトを選択し、リストからアクションを実行する必要なく、それらに対してアクションを実行できるようにすることです。

私のカスタム管理アクションは次のようになります:

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

私は、管理者変更フォームでこのアクションを呼び出すシンプルでクリーンな方法があると想定しています。この場合、querysetには、管理者が現在開いているオブジェクトのみが含まれます。

注:ボタンが変更フォームの下部、つまりSaveの上部ではなくHistoryボタンの横にあると、あまり目立たなくなります。

解決

解決策については Remi による回答を参照してください。これを機能させるには、次の修正が必要です。

1:response_changeのオーバーライドで、一部の変数の初期化が欠落しています。

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

2:新しい包含タグcustom_submit_rowは、adminではなくtemplatetagsに配置する必要があります( docs for custom templatetags を参照)

3:これは、しばらくの間失う可能性がある見落としです。 change_form.htmlでは、提案された行を変更する必要があるだけではありません。

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

submit_rowが表示される一番下の重要な行:

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

change_form.htmlのjavascriptブロックのすぐ上にあります)

19
dsalaj

change_form_template を見て、それを自分のカスタムテンプレートに設定し、response_changeメソッドをオーバーライドできます。

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からsite-packages/Django/contrib/admin/templates/change_form.htmlをコピーして、行44を編集します

 {% 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ブロックのすぐ上。

次に、admin.pyのどこかに新しい包含タグを登録するか、それをテンプレートタグに追加します。

@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>

コードはたくさんありますが、ほとんどがコピー/貼り付けです。お役に立てば幸いです。

16
Remi Smirra

ほとんどの人はおそらく考えずにこれを行いますが、管理者変更フォームを完全に上書きするのではなく単に拡張する必要があるという答えからは明確ではありませんでした。

custom_change_form.html

{% extends "admin/change_form.html" %}

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

{% block submit_buttons_bottom %}{% custom_submit_row %}{% endblock %}
8
Andrew Bird

または、submit_line.htmlファイルを拡張して、カスタムボタンを追加することもできます(変更ページの上部と下部の両方に)。

ファイルtemplates/adminyour_app_name/your_model_name.htmlは次で始まります:

{% extends "admin/submit_line.html" %}
{% load i18n admin_urls %}
<div class="submit-row">
  {% block submit-row %}  
     ... YOUR BUTTONS HERE ...
  {% endblock %}
</div>
1
Dos