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

 

Kommentare

Keine Kommentare vorhanden.

 

Kommentar schreiben