How do I add a placeholder on a CharField in Django?
Solution 1
Look at the widgets documentation. Basically it would look like:
q = forms.CharField(label='search',
widget=forms.TextInput(attrs={'placeholder': 'Search'}))
More writing, yes, but the separation allows for better abstraction of more complicated cases.
You can also declare a widgets
attribute containing a <field name> => <widget instance>
mapping directly on the Meta
of your ModelForm
sub-class.
Solution 2
For a ModelForm, you can use the Meta class thus:
from django import forms
from .models import MyModel
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'name': forms.TextInput(attrs={'placeholder': 'Name'}),
'description': forms.Textarea(
attrs={'placeholder': 'Enter description here'}),
}
Solution 3
The other methods are all good. However, if you prefer to not specify the field (e.g. for some dynamic method), you can use this:
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['email'].widget.attrs['placeholder'] = self.fields['email'].label or '[email protected]'
It also allows the placeholder to depend on the instance for ModelForms with instance specified.
Solution 4
Great question. There are three solutions I know about:
Solution #1
Replace the default widget.
class SearchForm(forms.Form):
q = forms.CharField(
label='Search',
widget=forms.TextInput(attrs={'placeholder': 'Search'})
)
Solution #2
Customize the default widget. If you're using the same widget that the field usually uses then you can simply customize that one instead of instantiating an entirely new one.
class SearchForm(forms.Form):
q = forms.CharField(label='Search')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['q'].widget.attrs.update({'placeholder': 'Search'})
Solution #3
Finally, if you're working with a model form then (in addition to the previous two solutions) you have the option to specify a custom widget for a field by setting the widgets
attribute of the inner Meta
class.
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
widgets = {
'body': forms.Textarea(attrs={'cols': 80, 'rows': 20})
}
Solution 5
You can use this code to add placeholder attr for every TextInput field in you form. Text for placeholders will be taken from model field labels.
class PlaceholderDemoForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PlaceholderDemoForm, self).__init__(*args, **kwargs)
for field_name in self.fields:
field = self.fields.get(field_name)
if field:
if type(field.widget) in (forms.TextInput, forms.DateInput):
field.widget = forms.TextInput(attrs={'placeholder': field.label})
class Meta:
model = DemoModel
Related videos on Youtube
Joelbitar
I like programming, I also like beer. Big fan of Android, Python and free software. I wish there were more hours on a day to write more code, there is always some project to finish.
Updated on September 28, 2020Comments
-
Joelbitar over 3 years
Take this very simple form for example:
class SearchForm(Form): q = forms.CharField(label='search')
This gets rendered in the template:
<input type="text" name="q" id="id_q" />
However, I want to add the
placeholder
attribute to this field with a value ofSearch
so that the HTML would look something like:<input type="text" name="q" id="id_q" placeholder="Search" />
Preferably I would like to pass the placeholder value in to
CharField
in the form class through a dictionary or something like:q = forms.CharField(label='search', placeholder='Search')
What would be the best way to accomplish this?
-
NotSimon over 10 years@OvedD, I know this is old, but see this question: stackoverflow.com/questions/4341739/…
-
Hamish Downer over 10 years@OvedD: see my answer for how to do this with a ModelForm
-
donturner almost 10 yearsThis is great because it avoids having to duplicate the lengthy instantiation of widgets for more complicated objects such as
ModelMultipleChoiceField
. Thanks! -
jozxyqk over 9 yearsSimilar spirit:
for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.label
, but I like your constructor method better. -
Will S about 8 yearsNote that in this case you cannot specify the field in the class body.
-
dspacejs almost 7 yearsIt's pretty stupid that you have to specify a widget to add a placeholder. You should be able to edit widget attributes without overriding the entire widget...
-
JxAxMxIxN almost 7 yearsThis was the easiest method for me - and it was nice that all the other attributes (i.e. required) were still automatically added without me having to specify them.
-
shellbye over 6 yearsFor chinese, you need the preceeding u like this: {'placeholder': u'搜索'}
-
Alberto Chiusole about 6 yearsI was about to write a solution as yours #2. I'd like to add that you can apply operations on all the fields by iterating over
self.fields
, e.g.:for field_name in self.fields: self.fields[field_name].widget.attrs.update({"placeholder": sth})
-
Dwayne Crooks about 6 years@AlbertoChiusole Yes you can, if that's what you want to do. Thanks for pointing it out.
-
Marian over 4 years@DwayneCrooks I suggest you update your #3 as per cdosborn's solution, because it is way shorter and more readable.
-
TylerH about 4 yearsPlease note that content must be in English on Stack Overflow. Aside from that, this appears to be a "me too" post, rather than an answer to the question posed above.
-
halfer about 4 yearsI would say that "me too" posts are OK if they add more detail. What about this approach is different to any of the others? What is the technique or essential learning here?
-
Leonard over 3 yearsThank you for this contribution. Could you please add some explanation, in order to help users understand in depth?