Как добавить местозаполнитель в 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})