DjangoのCharFieldにプレースホルダーを追加するにはどうすればよいですか?


195

たとえば、次のような非常に単純な形式を取ります。

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

これはテンプレートでレンダリングされます:

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

ただし、HTMLが次のようになるように、placeholderこのフィールドに値を指定して属性を追加しますSearch

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

できれば、プレースホルダの値をCharField辞書などのフォームクラスに渡したいと思います。

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

これを達成するための最良の方法は何でしょうか?

回答:


281

ウィジェットのドキュメントをご覧ください。基本的には次のようになります。

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

もっと書く、はい、しかし分離はより複雑なケースのより良い抽象化を可能にします。

サブクラスので直接マッピングwidgetsを含む属性を宣言することもできます。<field name> => <widget instance>MetaModelForm


宣言forms.TextInputを行うために指定する必要がありますattrs={'placeholder': 'Search'}か?
JhovaniC 2013

1
@OvedDは、私はこれが古いですけど、この質問を参照してください。stackoverflow.com/questions/4341739/...
NotSimon

1
@OvedD:ModelFormでこれを行う方法については私の回答を参照してください
Hamish Downer

1
プレースホルダーを追加するためにウィジェットを指定しなければならないのはかなり愚かです。ウィジェット全体を上書きせずにウィジェットの属性を編集できるはずです...
dspacejs '30

中国の場合、あなたはこのようにUに先行する必要があります:{「プレースホルダを」: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 2017年

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です。ありがとう!
ドンターナー2014年

1
同様の精神:for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.label、しかし私はあなたのコンストラクターメソッドがより好きです。
jozxyqk 2014

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

19

すばらしい質問です。私が知っている3つの解決策があります。

ソリューション#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

最後に、モデルフォームを使用している場合(前の2つのソリューションに加えて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})
Alberto Chiusole

@AlbertoChiusoleはい、それがあなたがやりたいことならできます。指摘してくれてありがとう。
ドウェイン

@DwayneCrooks cdosbornのソリューションに従って#3を更新することをお勧めします。
マリアン

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
Stack Overflowではコンテンツは英語である必要があります。それとは別に、これは上記の質問に対する答えではなく、「私も」の投稿のようです。
TylerH

「私も」という投稿は、詳細を追加すれば問題ないと思います。このアプローチについては、他のどのアプローチとも異なりますか?ここでのテクニックまたは本質的な学習は何ですか?
半分
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.