ฉันจะเพิ่มตัวยึดตำแหน่งบน 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
มันค่อนข้างโง่ที่คุณต้องระบุวิดเจ็ตเพื่อเพิ่มตัวแทน คุณควรจะสามารถแก้ไขแอททริบิวต์วิดเจ็ตได้โดยไม่ต้องลบวิดเจ็ตทั้งหมด ...
dspacejs

สำหรับคนจีนคุณต้องมีคนนำหน้าเช่นนี้: {'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'}),
        }

โปรดทราบว่าในกรณีนี้คุณไม่สามารถระบุเขตข้อมูลในร่างกายคลาส
Will 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
นี้ดีมากเพราะมันหลีกเลี่ยงไม่ต้องซ้ำ instantiation ModelMultipleChoiceFieldยาวของเครื่องมือสำหรับวัตถุที่มีความซับซ้อนมากขึ้นเช่น ขอบคุณ!
donturner

1
วิญญาณที่คล้ายกัน: for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.labelแต่ฉันชอบวิธีการสร้างของคุณดีขึ้น
jozxyqk

21

คุณสามารถใช้รหัสนี้เพื่อเพิ่มตัวยึดตำแหน่งสำหรับทุกฟิลด์ 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})
Alberto Chiusole

@AlbertoChiusole ใช่คุณทำได้ถ้านั่นคือสิ่งที่คุณต้องการจะทำ ขอบคุณที่ชี้นำ
Dwayne Crooks

@DwayneCrooks ฉันขอแนะนำให้คุณอัปเดต # 3 ของคุณตามวิธีการแก้ปัญหาของ cdosbornเพราะสั้นกว่าและอ่านง่ายกว่า
แมเรียน

1

ไม่พึงประสงค์ที่จะต้องทราบวิธีการสร้างอินสแตนซ์วิดเจ็ตเมื่อคุณต้องการแทนที่ตัวยึดตำแหน่ง

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

0

เวลาส่วนใหญ่ฉันเพียงต้องการให้ตัวยึดทั้งหมดเท่ากับชื่อ verbose ของฟิลด์ที่กำหนดในแบบจำลองของฉัน

ฉันได้เพิ่มมิกซ์อินเพื่อทำสิ่งนี้ในรูปแบบใด ๆ ที่ฉันสร้างได้ง่าย

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

ฉันจะบอกว่าโพสต์ "ฉันด้วย" ก็โอเคถ้าพวกเขาเพิ่มรายละเอียดเพิ่มเติม สิ่งที่เกี่ยวกับวิธีการนี้จะแตกต่างจากคนอื่น ๆ ? เทคนิคหรือการเรียนรู้ที่สำคัญที่นี่คืออะไร?
halfer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.