2016-01-20 11 views
9

Ich habe bereits eine benutzerdefinierte Admin-Aktion für mein Modell definiert, die perfekt wie erwartet funktioniert. Ich habe auch verschiedene Möglichkeiten zum Hinzufügen einer Schaltfläche zur Admin Formularseite hier auf SO untersucht. Der einzige Schritt, den ich vermisse, ist, wie man eine Schaltfläche in der Änderungsformularseite ausführt, um meine benutzerdefinierte Admin-Aktion mit dem aktuellen Objekt auszuführen.Django: Wie füge ich eine benutzerdefinierte Schaltfläche zur Admin-Formularseite hinzu, die eine Admin-Aktion ausführt?

Ziel ist es, dem Administrator zu ermöglichen, jedes Objekt einzeln zu prüfen und eine Aktion auszuführen, ohne zur Listenansicht zurückkehren zu müssen, das geprüfte Objekt auszuwählen und die Aktion aus der Liste auszuführen.

Meine benutzerdefinierten Admin-Aktion sieht wie folgt aus:

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

ich dort gehe davon eine einfache und saubere Art und Weise ist diese Aktion in Admin ändern Form des Aufrufs, in dem die queryset nur die zur Zeit den Admin geöffnet enthalten würde Objekt schaut an.

HINWEIS: Es wäre vorzuziehen, wenn die Schaltfläche am unteren Rand des Änderungsformulars neben Save Schaltfläche statt oben mit History Schaltfläche ist, die nicht sehr sichtbar ist.

Lösung

Siehe Antwort von Remi für die Lösung. Um sich zu machen, arbeiten die folgenden Korrekturen erforderlich:

1: In der Überschreibung von response_change Initialisierung einiger Variablen fehlt:

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

2: Neuaufnahme Tag custom_submit_row in templatetags platziert werden soll und nicht in admin (siehe docs for custom templatetags)

3: Dies ist das Versehen, auf das Sie etwas Zeit verlieren könnten. In change_form.html Sie nicht nur die vorgeschlagene Linie ändern müssen:

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

, sondern auch die wichtigeren Linie am unteren Rand, wo submit_row erscheint:

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

(es befindet sich direkt über dem Javascript-Block in change_form.html

)

Antwort

13

könnte Sie einen Blick auf die change_form_template und legen Sie es von Ihnen zu einer benutzerdefinierten Vorlage und überschreiben die response_change Methode:

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) 

Kopieren Sie die change_form.html von Ihrem site-packages/django/contrib/admin/templates/change_form.html und bearbeiten Sie die Linie 44

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

zu

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

Auch die Leitung überprüfen:

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

knapp über dem Javascript-Block .

Dann können Sie einen neuen Aufnahme-Tag irgendwo in Ihrem admin.py registrieren oder es zu templatetags hinzufügen:

@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 

Der Inhalt Ihrer 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> 

es eine Menge Code, aber meistens kopieren/einfügen. Ich hoffe, das hilft.

+0

Danke. Dies löste mein Problem und einige kleinere Korrekturen. Sehen Sie sie in meiner Frage aktualisieren. Es wäre schön, wenn Sie Ihre Antwort aktualisieren könnten, um diese Korrekturen zu übernehmen. – dsalaj

3

Die meisten Leute tun dies wahrscheinlich ohne nachzudenken, obwohl es aus der Antwort nicht klar war, dass das Admin-Änderungsformular einfach erweitert und nicht komplett überschrieben werden sollte.

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 %} 
Verwandte Themen