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.