Django'daki bir CharField'a nasıl yer tutucu ekleyebilirim?


195

Bu çok basit formu ele alalım örneğin:

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

Bu şablonda işlenir:

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

Ancak, HTML gibi bir şey görünecek şekilde placeholderbir değer ile bu alana özniteliği eklemek Searchistiyorum:

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

Tercihen CharField, bir sözlük veya benzeri bir şey aracılığıyla form sınıfında yer tutucu değerini geçirmek istiyorum:

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

Bunu başarmanın en iyi yolu ne olurdu?

Yanıtlar:


282

Bak widget'ları belgeler . Temel olarak şöyle görünecektir:

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

Daha fazla yazı, evet, ama ayrılık daha karmaşık vakaların daha iyi soyutlanmasını sağlar.

Ayrıca ilan edebilir widgetsbir içeren niteliğini <field name> => <widget instance>doğrudan eşleme Metasizin içinde ModelFormalt sınıfın.


bildirimi forms.TextInputyapmak için belirtmeniz gerekiyor attrs={'placeholder': 'Search'}mu?
— JhovaniC

1
@ODD, bunun eski olduğunu biliyorum, ama bu soruya bakın: stackoverflow.com/questions/4341739/…
— NotSimon

1
@ODD: bir ModelForm
— Hamish Downer

1
Yer tutucu eklemek için bir widget belirtmeniz oldukça aptalca. Tüm widget'ı geçersiz
— kılmadan

Çince için, aşağıdaki gibi
— uya

60

Bir ModelForm için Meta sınıfını şu şekilde kullanabilirsiniz:

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

Bu durumda sınıf gövdesindeki alanı belirtemeyeceğinizi unutmayın.
— S

Bu benim için en kolay yöntemdi - ve diğer tüm özelliklerin (yani gerekli), ben belirtmek zorunda kalmadan otomatik olarak eklenmesi güzeldi.
— JxAxMxIxN

41

Diğer yöntemlerin hepsi iyidir. Ancak, alanı belirtmemeyi tercih ederseniz (örneğin, bazı dinamik yöntemler için), bunu kullanabilirsiniz:

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'

Ayrıca yer tutucunun, belirtilen örneği olan ModelForms örneğine bağımlı olmasına izin verir.


7
Bu harika, çünkü daha karmaşık nesneler için widget'ların uzun süre örneğini çoğaltmak zorunda kalmıyor ModelMultipleChoiceField. Teşekkürler!
— donturner

1
Benzer ruh: for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.labelama yapıcı yönteminizi daha çok seviyorum.
— jozxyqk

21

Bu kodu, formunuzdaki her TextInput alanı için yer tutucu attr eklemek için kullanabilirsiniz. Yer tutucuların metinleri model alan etiketlerinden alınacaktır.

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

Harika bir soru. Bildiğim üç çözüm var:

Çözüm # 1

Varsayılan widget'ı değiştirin.

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

Çözüm # 2

Varsayılan widget'ı özelleştirin. Alanın genellikle kullandığı widget'ı kullanıyorsanız, tamamen yeni bir tane oluşturmak yerine bu widget'ı özelleştirebilirsiniz.

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

Çözüm # 3

Son olarak, bir model formuyla çalışıyorsanız ( önceki iki çözüme ek olarak ) widgets, iç Metasınıfın niteliğini ayarlayarak bir alan için özel bir widget belirtme seçeneğiniz vardır .

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

1
Sizinkinin # 2'si gibi bir çözüm yazmak üzereydim. self.fieldsfor field_name in self.fields: self.fields[field_name].widget.attrs.update({"placeholder": sth})
— Tekrarlayarak

@AlbertoChiusole Evet yapabilirsiniz, eğer bunu yapmak istiyorsanız. Gösterdiğiniz için teşekkürler.
— Dwayne Crooks

@DwayneCrooks Sana göre senin 3. güncellemek önermek cdosborn çözümüyle bu yol daha kısa ve daha okunabilir olduğundan,.
— Marian

1

Sadece yer tutucusunu geçersiz kılmak istediğinizde bir widget'ın nasıl somutlaştırılacağını bilmek istenmez.

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

0

Çoğu zaman tüm yer tutucuların modellerimde tanımlanan alanın ayrıntılı adına eşit olmasını istiyorum

Bunu oluşturduğum herhangi bir forma kolayca yapmak için bir mixin ekledim,

class ProductForm(PlaceholderMixin, ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'description', 'location', 'store')

Ve

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

Metodunuza baktıktan sonra çözmek için bu metodu kullandım.

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
Yığın Taşması durumunda içeriğin İngilizce olması gerektiğini lütfen unutmayın. Bunun yanı sıra, yukarıda sorulan soruya bir cevap olmaktan ziyade, bu bir "ben de" gönderi gibi görünüyor.
— TylerH

Daha fazla ayrıntı eklerseniz "ben de" gönderilerin iyi olduğunu söyleyebilirim. Peki ya bu yaklaşım diğerlerinden farklı? Buradaki teknik veya temel öğrenme nedir?
— halfer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.