django newforms: forms.ModelForm

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 24. Juli 2008, 16:21

django forms.ModelForm ist ja eine schöne Sache. Ich nutzte das bei einem Model mit einem many-to-many Eintrag. Dieser wird per MultipleChoiceField dargestellt.
Das Problem: Es wird die Anzahl der Einträge nicht limitiert. Der html code sieht so aus:

Code: Alles auswählen

...
<select multiple="multiple" name="tags" id="id_tags">
...
Dem widget könnte man theoretisch noch ein attrs={"size": 5} mitgeben, dann wäre die größe beschränkt, rauskommen müßte dann das:

Code: Alles auswählen

...
<select multiple="multiple" name="tags" id="id_tags" size="5">
...
Das Problem ist also, wie gibt planzt man das widget attr ein, ohne in der ModelForm Klasse das ganze Feld komplett selber zu definieren?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 24. Juli 2008, 16:34

Ah... Ein Weg habe ich gefunden. Man kann im __init__ der ModelForm was basteln, siehe Zeile 18:

Code: Alles auswählen

from django import newforms as forms
from django.contrib.auth.models import User

# Paar test user erstellen
for i in xrange(1,6):
    new_user = User(username="test%s" % i, email="test%s@invalid.org" % i)
    new_user.save()

print User.objects.all()

print "-"*80

class UserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)

        # attribute des widget ändern:
        self.fields['user_permissions'].widget.attrs["size"] = 5
         
    class Meta:
        model = User

users_form = UserForm()
print "-"*80
print users_form.as_p()
Aber so richtig schön ist das nicht...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Freitag 25. Juli 2008, 08:09

Ohne es ausprobiert zu haben, aber ein `Field` hat eine Methode `widget_attrs()`, die man überschreiben könnte, um zusätzliche Attribute zu einem Widget hinzuzufügen. Du könntest dir damit also ein eigenes `ModelMultipleChoiceField` haben und das in deiner `ModelForm` benutzen. Willst du das nicht explizit überschreiben, kannst du in einem eigenen `ManyToManyField` die Methode `formfield()` überschreiben. Das ist aber auch nicht so ganz einfach, denn da kommt ein fertiges Exemplar zurück und man kann nicht einfach nur die Klasse ändern. Schlechtes Design. Speziell da `Field` bereits über die Choices eines `Select`-Widgets weiß...

Deine Lösung ist somit gar nicht so schlecht, denn sie gräbt nicht das halbe System um, sondern patcht das richtige Attribut kurz und schmerzlos ;)

Stefan
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 25. Juli 2008, 12:30

Hm. Ob man über __init__ evtl. auch andere Dinge noch abändern kann? Wie z.B. einen help_text einfügen oder ein min_length?

EDIT: Habs mal publik gemacht: http://www.djangosnippets.org/snippets/916/

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten