2012-08-23 5 views
20

Ich muss meinem Modell ein zusätzliches Feld hinzufügen. Mein Ansatz ist:Angeben des Widgets für das zusätzliche Formularfeld für das Formular (Django)

class MyForm(forms.ModelForm): 
    extra_field = forms.CharField() 
    class Meta: 
     model = MyModel 
     widgets = { 
      #Does not work 
      'extra_field': forms.Textarea(attrs={'placeholder': u'Bla bla'}), 
     } 

Aber es scheint, dass Widget Definition für extra_field bei class Meta wird ignoriert, weil ich einen nackten Eingang-Tag statt TextArea- auf einer Vorlage. So bewerbe ich mir nächsten Ansatz:

class MyForm(forms.ModelForm): 
    #It works fine 
    extra_field = forms.CharField(widget=forms.Textarea()) 
    class Meta: 
     model = MyModel 

Es funktioniert perfekt für mich, aber ich habe Widgets für Formularfelder in class Meta Erklärung angeben. So frage ich mich:

Warum meine erste Annäherung nicht funktioniert? Was mache ich falsch?

+0

Sind Sie sicher, dass Sie auf Django sind 1.4? Form.Meta.widgets wurde in Django 1.4 eingeführt. – jpic

+0

Ja. 'Django Version: \t 1.4' –

Antwort

23

Es spielt keine Rolle, ob es ein zusätzliches Feld ist. Dies funktioniert:

class FooForm(forms.ModelForm): 
    class Meta: 
     model = People 
     widgets = { 
      'name': forms.Textarea(attrs={'placeholder': u'Bla bla'}), 
     } 

Dies gilt nicht:

class FooForm(forms.ModelForm): 
    name = forms.CharField() 

    class Meta: 
     model = People 
     widgets = { 
      'name': forms.Textarea(attrs={'placeholder': u'Bla bla'}), 
     } 

Dies ist not documented indeed, das ist das Beste, was ich in der Dokumentation finden konnte, die zu diesem Verhalten in Zusammenhang stehen könnten (vielleicht tut es nicht, es ist nur das beste, was ich finden konnte):

Wenn Sie explizit ein Formularfeld wie folgt instanziiert nimmt Django, dass Sie vollständig sein Verhalten definieren wollen [...] müssen Sie die relevanten Argumente explizit angeben, wenn Sie das Formularfeld deklarieren.

Die Umsetzung dieses Verhalten ist in django/forms/models.py Linie 219:.

204   if opts.model: 
    205    # If a model is defined, extract form fields from it. 
    206    fields = fields_for_model(opts.model, opts.fields, 
    207          opts.exclude, opts.widgets, formfield_callback) 
    208    # make sure opts.fields doesn't specify an invalid field 
    209    none_model_fields = [k for k, v in fields.iteritems() if not v] 
    210    missing_fields = set(none_model_fields) - \ 
EE 211        set(declared_fields.keys()) 
    212    if missing_fields: 
    213     message = 'Unknown field(s) (%s) specified for %s' 
    214     message = message % (', '.join(missing_fields), 
    215          opts.model.__name__) 
    216     raise FieldError(message) 
    217    # Override default model fields with any custom declared ones 
    218    # (plus, include all the other declared fields). 
    219    fields.update(declared_fields) 

Nach Linie 206, die Felder [ 'name'] Widget in der Tat die Textarea in angegeben ist Meta.Widgets.

In Zeile 219 werden Felder mit deklarierten Feldern und Feldern ['Name'] aktualisiert.widget wird zu django.forms.widgets.TextInput, das der Standardwert für CharField ist.

Offensichtlich haben explizite Felddefinitionen Priorität.

Danke für die Frage, gut zu wissen, große Frage.

+0

Danke für die klare Antwort. –

+0

diese Antwort funktioniert nicht für mich. vielleicht änderte Django das Verhalten –

+0

Das soll noch funktionieren, vielleicht noch eine Frage stellen? – jpic

2

löste ich die Situation oben mit den folgenden:

class FooForm(forms.ModelForm): 
    name = forms.CharField(widget=TextArea(attrs={'placeholder': u'Bla bla'})) 
    class Meta: 
     model = People 
+0

Wird dadurch auch der Feldname zur Tabelle hinzugefügt? – tilaprimera