I have to add extra field to my model form. My approach is:
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'}), }
But it seems that widget definition for extra_field
at class Meta
is ignored, because i have a bare input tag instead of textarea on a template. So I apply next approach:
class MyForm(forms.ModelForm): #It works fine extra_field = forms.CharField(widget=forms.Textarea()) class Meta: model = MyModel
It works perfectly for me, but I used to specify widgets for form fields at class Meta
declaration. So I wonder:
Why my first approach doesn't work? What I am doing wrong?
To answer your question, with the new migration introduced in Django 1.7, in order to add a new field to a model you can simply add that field to your model and initialize migrations with ./manage.py makemigrations and then run ./manage.py migrate and the new field will be added to your DB.
Overriding the default fields To specify a custom widget for a field, use the widgets attribute of the inner Meta class. This should be a dictionary mapping field names to widget classes or instances. The widgets dictionary accepts either widget instances (e.g., Textarea(...) ) or classes (e.g., Textarea ).
To create ModelForm in django, you need to specify fields. Just associate the fields to first_name and lastName. Under the Meta class you can add : fields = ['first_name','lastName']. @Shishir solution works after I add that line. or you can try solution in Jihoon answers by adding vacant fields.
Enter Venue Name, Address and Zip/Post Code in the blank form, but leave the Contact Phone, Web Address and Email Address fields blank. Click “Save”. Your screen should look something like Figure 7.5.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With