Как добавить местозаполнитель в CharField в Django?
Возьмите эту очень простую форму, например:
class SearchForm(Form):
q = forms.CharField(label='search')
Это отображается в шаблоне:
<input type="text" name="q" id="id_q" />
Однако я хочу добавить атрибут placeholder
в это поле со значением Search
чтобы HTML выглядел примерно так:
<input type="text" name="q" id="id_q" placeholder="Search" />
Предпочтительно я хотел бы передать значение заполнителя в CharField
в классе формы через словарь или что-то вроде:
q = forms.CharField(label='search', placeholder='Search')
Каков будет лучший способ сделать это?
Ответы
Ответ 1
Посмотрите документацию по виджетам. В основном это выглядело бы так:
q = forms.CharField(label='search',
widget=forms.TextInput(attrs={'placeholder': 'Search'}))
Больше написания, да, но разделение позволяет лучше абстрагировать более сложные случаи.
Вы также можете объявить атрибут widgets
, содержащий сопоставление <field name> => <widget instance>
непосредственно на Meta
вашего подкласса ModelForm
.
Ответ 2
Для ModelForm вы можете использовать класс Meta таким образом:
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'}),
}
Ответ 3
Другие методы хороши. Однако, если вы предпочитаете не указывать поле (например, для некоторого динамического метода), вы можете использовать это:
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['email'].widget.attrs['placeholder'] = self.fields['email'].label or '[email protected]'
Он также позволяет заполнителю зависеть от экземпляра для ModelForms с указанным экземпляром.
Ответ 4
Вы можете использовать этот код, чтобы добавить placeholder attr для каждого поля TextInput в вашей форме. Текст для заполнителей будет взят из ярлыков полей модели.
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
Ответ 5
Отличный вопрос. Я знаю о трех решениях:
Решение № 1
Замените виджет по умолчанию.
class SearchForm(forms.Form):
q = forms.CharField(
label='Search',
widget=forms.TextInput(attrs={'placeholder': 'Search'})
)
Решение №2
Настроить виджет по умолчанию. Если вы используете тот же виджет, который обычно использует поле, вы можете просто настроить его вместо создания нового.
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'})
Решение № 3
Наконец, если вы работаете с модельной формой (в дополнение к двум предыдущим решениям), вы можете указать собственный виджет для поля, установив атрибут widgets
внутреннего класса Meta
.
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
widgets = {
'body': forms.Textarea(attrs={'cols': 80, 'rows': 20})
}
Ответ 6
Нежелательно знать, как создать экземпляр виджета, когда вы просто хотите переопределить его заполнитель.
q = forms.CharField(label='search')
...
q.widget.attrs['placeholder'] = "Search"
Ответ 7
Большую часть времени я просто хочу иметь заполнитель, равный verbose_name, определенному в models.py, чтобы форма оставалась минимальной.
Я добавил миксин, чтобы легко сделать это для любой формы, которую я создаю,
class ProductForm(PlaceholderMixin, ModelForm):
class Meta:
model = Product
fields = ('name', 'description', 'location', 'store')
И
class PlaceholderMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs):
field_names = [field_name for field_name, _ in self.fields.items()]
for field_name in field_names:
field = self.fields.get(field_name)
field.widget.attrs.update({'placeholder': field.label})