It doesn't matter if it's an extra field. This works:
class FooForm(forms.ModelForm):
class Meta:
model = People
widgets = {
'name': forms.Textarea(attrs={'placeholder': u'Bla bla'}),
}
This doesn't:
class FooForm(forms.ModelForm):
name = forms.CharField()
class Meta:
model = People
widgets = {
'name': forms.Textarea(attrs={'placeholder': u'Bla bla'}),
}
This is not documented indeed, that's the best I could find in the docs that could relate to that behaviour (maybe it doesn't, it's just the best i could find):
If you explicitly instantiate a form field like this, Django assumes that you want to completely define its behavior [...] you must set the relevant arguments explicitly when declaring the form field.
The implementation of this behaviour is in django/forms/models.py line 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)
After line 206, fields['name'].widget is indeed the Textarea specified in Meta.widgets.
At line 219, fields is updated with declared_fields, and fields['name'].widget becomes django.forms.widgets.TextInput which is the default for CharField.
Apparently, explicit field definitions have priority.
Thanks for asking, good to know, great question.