Як додати заповнювач на CharField у Django?


195

Візьмемо для прикладу цю дуже просту форму:

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

Який найкращий спосіб досягти цього?

Відповіді:


282

Подивіться на документацію віджетів . В основному це виглядатиме так:

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

Більше писати, так, але розділення дозволяє краще абстрагувати складніші справи.

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


чи потрібно вказати, forms.TextInputщоб зробити attrs={'placeholder': 'Search'}декларацію?
JhovaniC

1
@OvedD, я знаю , що це старий, але подивіться на це питання: stackoverflow.com/questions/4341739 / ...
NotSimon

1
@OvedD: дивіться мою відповідь, як це зробити за допомогою ModelForm
Hamish Downer

1
Дуже дурно, що вам потрібно вказати віджет, щоб додати заповнювач. Ви повинні мати можливість редагувати атрибути віджетів, не
змінюючи

Для китайської мови вам потрібно відповідати наступним чином: {'placeholder': u '搜索'}
shellbye

60

Для 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'}),
        }

Зауважте, що в цьому випадку ви не можете вказати поле в тілі класу.
Буде S

Це був найпростіший метод для мене - і було приємно, що всі інші атрибути (тобто необхідні) все ще були автоматично додані, не вказуючи їх.
JxAxMxIxN

41

Інші методи - все добре. Однак якщо ви віддаєте перевагу не вказувати поле (наприклад, для деякого динамічного методу), ви можете використовувати це:

def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields['email'].widget.attrs['placeholder'] = self.fields['email'].label or 'email@address.nl'

Це також дозволяє заповнити заповнення залежно від екземпляра для ModelForms із вказаним екземпляром.


7
Це чудово, оскільки це дозволяє уникнути дублювання тривалої інстанції віджетів для більш складних об'єктів, таких як ModelMultipleChoiceField. Дякую!
donturner

1
Схожий дух:, for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.labelале мені більше подобається твій метод конструктора.
jozxyqk

21

Ви можете використовувати цей код, щоб додати 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

20

Чудове запитання. Я знаю три рішення:

Рішення №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})
Альберто Кюсоле

@AlbertoChiusole Так, ви можете, якщо це те, що ви хочете зробити. Дякуємо, що вказали на це.
Дуейн Крукс

@DwayneCrooks Я пропоную вам оновити номер №3 відповідно до рішення cdosborn , оскільки це набагато коротше і читабельніше.
Маріан

1

Небажано знати, як інстанціювати віджет, коли ви просто хочете змінити його заповнювач.

    q = forms.CharField(label='search')
    ...
    q.widget.attrs['placeholder'] = "Search"

0

Більшу частину часу я просто хочу, щоб усі заповнювачі дорівнювали багатослівному імені поля, визначеному в моїх моделях

Я додав міксин, щоб легко зробити це в будь-якій створеній мною формі,

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

-2

Переглянувши ваш метод, я використав цей метод для його вирішення.

class Register(forms.Form):
    username = forms.CharField(label='用户名', max_length=32)
    email = forms.EmailField(label='邮箱', max_length=64)
    password = forms.CharField(label="密码", min_length=6, max_length=16)
    captcha = forms.CharField(label="验证码", max_length=4)

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    for field_name in self.fields:
        field = self.fields.get(field_name)
        self.fields[field_name].widget.attrs.update({
            "placeholder": field.label,
            'class': "input-control"
        })

2
Зауважте, що вміст повинен бути англійською мовою на "Переповнення стека". Крім цього, це, здається, є повідомленням "я теж", а не відповіддю на поставлене вище питання.
TylerH

Я б сказав, що повідомлення "я теж" добре, якщо вони додають більше деталей. Чим цей підхід відрізняється від будь-якого з інших? Яка тут техніка чи основне навчання?
половина
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.