In den vergangenen Spass mit Newforms-Admin Beiträgen hab ich immer wieder gezeigt, wie man das Widget (die HTML-Ausgabe) eines Feldes beeinflusst und ändert.
Als Beispiel nochmal ein simples Model, bei dem letztendlich der Titel in großer Schrift ausgegeben werden soll.
from django.db import models
class Foobar(models.Model):
title = models.CharField(max_length=100)
text = models.TextField(blank=True)
Also basteln wir uns -- wie gehabt -- eine ModelAdmin-Klasse und darin eine Methode formfield_for_dbfield. Diese durchläuft alle Felder und wenn sie auf den passenden Titel trifft, ändert sie das Widget dazu.
from django.contrib import admin
from django import forms
from django.utils.safestring import mark_safe
from .models import Foobar
class BigTitleWidget(forms.widgets.Input):
def render(self, name, value, attrs=None):
field = '<input name="%s" value="%s" style="font-size:1.5em"/>' % (name, value)
return mark_safe(field)
class FoobarAdmin(admin.ModelAdmin):
def formfield_for_dbfield(self, db_field, **kwargs):
field = super(FoobarAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == "title":
field.widget = BigTitleWidget()
return field
admin.site.register(Foobar, FoobarAdmin)
Aber ist das nicht super hässlich? Irgendwann bin ich mal über einen Codeblock von Jannis gestolpert und hab gesehen, dass die ModelAdmin-Klasse ein Attribut form besitzt, dass das automatisch generierte ModelForm mit einem eigenen überschreiben kann. Hey, und das ist sogar dokumentiert.
from django.contrib import admin
from django import forms
from django.utils.safestring import mark_safe
from .models import Foobar
class BigTitleWidget(forms.widgets.Input):
def render(self, name, value, attrs=None):
field = '<input name="%s" value="%s" style="font-size:1.5em"/>' % (name, value)
return mark_safe(field)
class FoobarForm(forms.ModelForm):
title = forms.CharField(widget=BigTitleWidget())
class FoobarAdmin(admin.ModelAdmin):
form = FoobarForm
admin.site.register(Foobar, FoobarAdmin)
Das ist doch viel schöner! :-)
Also nie wieder formfield_for_dbfield? Nicht ganz, denn innerhalb des ModelForms hat man keinen Zugriff auf die anderen Parameter des aktuellen Admin-Views. Will man dem Widget weitere Parameter übergeben (wie z.B. die aktuelle User-ID, hier erklärt, führt der Weg weiterhin über formfield_for_dbfield.
Martin Geber Jan. 23, 2009
Wieder einmal ein großartiger Artikel von der Insel. Super
Habe wieder mal etwas gelernt :P
VG ein Namensvetter.
Jens May 19, 2009
Wenn man allerdings eine eigene Form nutzt, kann man so keine Meta Informationen aus dem Model übernehmen. Das ist IMHO doof. Mit formfield_for_dbfield wird aber nur widget getauscht und alles andere kommt aus dem Model. Siehe auch: http://www.jensdiemer.de/_command/118/blog/detail/5/
Martin Mahner May 19, 2009
Hast du den letzten Absatz gelesen? :D