Как добавить заполнитель на CharField в Django?

152

Возьмите эту очень простую форму, например.

class SearchForm(Form):
   q = forms.CharField(label='search')

Это отображается в шаблоне:

<input type="text" name="q" id="id_q" />

Однако я хочу добавить атрибут "placeholder" в это поле со значением "Поиск", чтобы HTML выглядел примерно так:

<input type="text" name="q" id="id_q" placeholder="Search" />

Я хотел бы передать значение placeholder в CharField в классе формы через словарь или что-то вроде:

q = forms.CharField(label='search', placeholder='Search')

Каким будет лучший способ достичь этого?

Теги:
django-forms

5 ответов

216
Лучший ответ

Посмотрите документацию по виджетам. В основном это выглядело бы так:

q = forms.CharField(label='search', 
                    widget=forms.TextInput(attrs={'placeholder': 'Search'}))

Больше написания, да, но разделение позволяет лучше абстрагировать более сложные случаи.

Вы также можете объявить атрибут widgets, содержащий сопоставление <field name> => <widget instance> непосредственно на Meta вашего подкласса ModelForm.

  • 0
    вам нужно указать forms.TextInput для объявления attrs={'placeholder': 'Search'} ?
  • 1
    @OvedD, я знаю, что это старый, но вижу этот вопрос: stackoverflow.com/questions/4341739/…
Показать ещё 3 комментария
39

Для 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'}),
        }
  • 0
    Обратите внимание, что в этом случае вы не можете указать поле в теле класса.
  • 0
    Это был самый простой способ для меня - и было приятно, что все остальные атрибуты (т.е. обязательные) все равно добавлялись автоматически, без необходимости их указывать.
25

Другие методы хороши. Однако, если вы предпочитаете не указывать поле (например, для некоторого динамического метода), вы можете использовать это:

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 с указанным экземпляром.

  • 6
    Это замечательно, поскольку позволяет избежать дублирования длинных экземпляров виджетов для более сложных объектов, таких как ModelMultipleChoiceField . Спасибо!
  • 1
    Аналогичный дух: for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.label , но мне больше нравится ваш метод конструктора.
19

Вы можете использовать этот код, чтобы добавить 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
7

Отличный вопрос. Я знаю о трех решениях:

Решение № 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})
        }
  • 1
    Я собирался написать решение как твое # 2. Я хотел бы добавить, что вы можете применять операции ко всем полям, перебирая self.fields , например: for field_name in self.fields: self.fields[field_name].widget.attrs.update({"placeholder": sth})
  • 0
    @AlbertoChiusole Да, вы можете, если это то, что вы хотите сделать. Спасибо за указание на это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню