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.