Django Admin: Popup nach Änderung schließen

Veröffentlich am 18.11.2008, 14:24

Ich arbeite derzeit an einem netten CMS Modul für Django, bei dem die einzelnen Seiten im Baukastenprinzip inkl. Drag+Drop zusammengesetzt werden. Beim Bearbeiten der einzelnen PageElements (die Blöcke, aus denen die Seite besteht) fiel mir auf, dass beim Speichern der REQUEST Parameter _popup nicht berücksichtigt wird, sondern stattdessen zur Change List des zu bearbeitenden Models gewechselt wird.

Dieses Stück Code schafft Abhilfe und schließt das Popup Window nach dem Speichern auf die gleiche Weise, wie beim Hinzufügen von Objekten bei z.b. ForeignKeys.

class ClosablePopupAdmin(admin.ModelAdmin):
    def response_change(self, request, obj):
        response = super(ClosablePopupAdmin, self).response_change(request, obj)
        if request.POST.has_key("_popup"):
            return HttpResponse('<script type="text/javascript">window.close();</script>')
        return response

Sehr simpel aber funktioniert ;-)

Tags: django, newforms-admin, popup

Weiterlesen, 0 Kommentar(e)

 

AdminFileWidget mit Delete-Funktion

Veröffentlich am 06.11.2008, 10:00

Nachdem ich bereits längere Zeit nach einer Möglichkeit gesucht habe, den Inhalt von File-Feldern über Newforms-Admin löschen zu können, habe ich nun selbst ein kleines Widget geschrieben, welches genau das erledigt.

Neugeschrieben? Manch einer wird sich fragen, warum ich nicht eines der existierenden Snippets (#1, #2, es gibt sicher noch weitere) von djangosnippets.org nutze. Ganz einfach: sie machen eine Änderung des Models notwendig und genau das will ich nicht. Ich möchte meine Models nicht aufgrund eines Admin-Features ändern müssen.

Ich beginne erstmal mit dem Code selbst, Erläuterungen folgen:

from django.utils.safestring import mark_safe

class AdminDeleteFileWidget(admin.widgets.AdminFileWidget):
    def render(self, name, value, attrs=None):
        output = []
        output.append(super(AdminDeleteFileWidget, self).render(name, value, attrs))
        output.append('<br /><input type="checkbox" name="adfw_%s_delete" /> %s' % (name, 'Delete'))
        return mark_safe(u''.join(output))

class DeleteModelAdmin(admin.ModelAdmin):
    def response_change(self, request, obj):
        from django.db.models.fields.files import FileField
        for field in obj._meta.fields:
            if isinstance(field, FileField):
                if request.POST.has_key('adfw_%s_delete' % field.name):
                    try:
                        file = getattr(obj, field.name)
                        file.delete()
                    except:
                        pass

        return super(DeleteModelAdmin, self).response_change(request, obj)

    def formfield_for_dbfield(self, db_field, **kwargs):
        field = super(DeleteModelAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if field and isinstance(field.widget, admin.widgets.AdminFileWidget):
            field.widget = AdminDeleteFileWidget()
        return field

Der Aufbau ist relativ simpel. Ich habe die AdminFileWidget Klasse von Newforms-Admin beerbt und an die reguläre Ausgabe noch eine Checkbox zum Löschen angehängt. Der Name ist bewusst kompliziert gewählt, um zu vermeiden das ein normales Model-Feld überschrieben wird (adwf_feldname_delete).

Beim laden des Formulars wird für jedes Model-Feld die Methode formfield_for_dbfield aufgerufen. Diese Methode wird durch die DeleteModelAdmin Klasse überschrieben und prüft für jedes Feld, ob es sich um ein File-Feld handelt. Wenn ja, wird das Widget durch das AdminDeleteFileWidget ausgetauscht.

Beim Speichern des Formulars wird die Methode response_change aufgerufen. Hier prüft die Methode für jedes Model-Feld, ob es sich um ein File-Feld handelt und wenn dies zutrifft prüft die Methode weiter, ob das eine Datei hinterlegt ist. Ist das der Fall, wird das Vorhandensein der POST Variable adfw_feldname_delete abgefragt und bei erfolg die Datei gelöscht.

Um diese Funktionalität einsetzen zu können, müssen die Model-spezifischen Adminklassen von DeleteModelAdmin statt admin.ModelAdmin erben.

Tags: django, newforms-admin, widget

Weiterlesen, 0 Kommentar(e)