Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying widget for model form extra field (Django)

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?

like image 743
Serhii Holinei Avatar asked Aug 23 '12 18:08

Serhii Holinei


People also ask

How do I add a field to an existing model in Django?

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.

How do you override a field widget in form for model?

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 ).

How do I customize Modelan in Django?

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.

How do I make a field optional in Django?

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.


Video Answer


1 Answers

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.

like image 53
jpic Avatar answered Sep 17 '22 17:09

jpic