如何在Django中的CharField上添加占位符?

Joe*_*tar 190 python django django-forms

以这个非常简单的形式为例.

class SearchForm(Form):
    q = forms.CharField(label='search')
Run Code Online (Sandbox Code Playgroud)

这将在模板中呈现:

<input type="text" name="q" id="id_q" />
Run Code Online (Sandbox Code Playgroud)

但是,我想将"占位符"属性添加到此字段,其值为"搜索",以便HTML看起来像:

<input type="text" name="q" id="id_q" placeholder="Search" />
Run Code Online (Sandbox Code Playgroud)

我希望通过字典或类似的方式将占位符值传递给表单类中的CharField:

q = forms.CharField(label='search', placeholder='Search')
Run Code Online (Sandbox Code Playgroud)

实现这一目标的最佳方法是什么?

Mik*_*iak 274

查看小部件文档.基本上它看起来像:

q = forms.CharField(label='search', 
                    widget=forms.TextInput(attrs={'placeholder': 'Search'}))
Run Code Online (Sandbox Code Playgroud)

更多的写作,是的,但分离允许更好地抽象更复杂的情况.

您也可以声明widgets包含一个属性<field name> => <widget instance>直接映射Meta你的ModelForm子类.

  • @OvedD:请参阅我的答案,了解如何使用 ModelForm 执行此操作 (2认同)
  • 您必须指定一个小部件来添加占位符,这是非常愚蠢的。您应该能够编辑小部件属性,而无需覆盖整个小部件...... (2认同)

Ham*_*ner 55

对于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'}),
        }
Run Code Online (Sandbox Code Playgroud)


Mar*_*ark 36

其他方法都很好.但是,如果您不想指定字段(例如,对于某些动态方法),您可以使用:

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'
Run Code Online (Sandbox Code Playgroud)

它还允许占位符依赖于具有指定实例的ModelForms的实例.

  • 这很好,因为它避免了为更复杂的对象(如ModelMultipleChoiceField`)复制小部件的冗长实例化.谢谢! (6认同)
  • 类似的精神:`for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.label`,但我更喜欢你的构造函数方法。 (2认同)

Yev*_*lev 21

您可以使用此代码为表单中的每个TextInput字段添加占位符attr.占位符文本将从模型字段标签中获取.

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
Run Code Online (Sandbox Code Playgroud)


Dwa*_*oks 17

好问题.我知道有三种解决方案:

解决方案#1

替换默认小部件.

class SearchForm(forms.Form):  
    q = forms.CharField(
            label='Search',
            widget=forms.TextInput(attrs={'placeholder': 'Search'})
        )
Run Code Online (Sandbox Code Playgroud)

解决方案#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'})
Run Code Online (Sandbox Code Playgroud)

解决方案#3

最后,如果您正在使用模型表单(除了前两个解决方案),您可以选择通过设置widgets内部Meta类的属性为字段指定自定义窗口小部件.

class CommentForm(forms.ModelForm):  
    class Meta:
        model = Comment
        widgets = {
            'body': forms.Textarea(attrs={'cols': 80, 'rows': 20})
        }
Run Code Online (Sandbox Code Playgroud)


小智 5

大多数时候,我只是希望所有占位符等于模型中定义的字段的详细名称

我添加了一个 mixin 来轻松地对我创建的任何表单执行此操作,

class ProductForm(PlaceholderMixin, ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'description', 'location', 'store')
Run Code Online (Sandbox Code Playgroud)

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})
Run Code Online (Sandbox Code Playgroud)