Come faccio ad aggiungere un segnaposto su un CharField in Django?


195

Prendi questo modulo molto semplice per esempio:

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

Questo viene reso nel modello:

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

Tuttavia, voglio aggiungere l' placeholderattributo a questo campo con un valore in Searchmodo che l'HTML sia simile a:

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

Preferibilmente, vorrei passare il valore del segnaposto nella CharFieldclasse del modulo attraverso un dizionario o qualcosa del genere:

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

Quale sarebbe il modo migliore per raggiungere questo obiettivo?

Risposte:


281

Guarda la documentazione dei widget . Fondamentalmente sembrerebbe:

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

Più scrittura, sì, ma la separazione consente una migliore astrazione di casi più complicati.

Puoi anche dichiarare un widgetsattributo contenente una <field name> => <widget instance>mappatura direttamente sulla Metatua ModelFormsottoclasse.


devi specificare forms.TextInputper fare la attrs={'placeholder': 'Search'}dichiarazione?
JhovaniC,

1
@OvedD, so che questo è vecchio, ma vedere questa domanda: stackoverflow.com/questions/4341739/...
NotSimon

1
@OvedD: vedi la mia risposta su come fare questo con un ModelForm
Hamish Downer

1
È abbastanza stupido che devi specificare un widget per aggiungere un segnaposto. Dovresti essere in grado di modificare gli attributi del widget senza sovrascrivere l'intero widget ...
dspacejs,

Per il cinese, hai bisogno che ti preceda in questo modo: {'segnaposto': u '搜索'}
shellbye

60

Per un ModelForm, è possibile utilizzare la classe Meta in questo modo:

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

Si noti che in questo caso non è possibile specificare il campo nel corpo della classe.
Will S

Questo è stato il metodo più semplice per me - ed è stato bello che tutti gli altri attributi (cioè richiesti) siano stati aggiunti automaticamente senza che sia necessario specificarli.
JxAxMxIxN il

41

Gli altri metodi sono tutti buoni. Tuttavia, se si preferisce non specificare il campo (ad es. Per un metodo dinamico), è possibile utilizzare questo:

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'

Inoltre, consente al segnaposto di dipendere dall'istanza per ModelForms con l'istanza specificata.


7
Questo è fantastico perché evita di dover duplicare la lunga istanza dei widget per oggetti più complicati come ModelMultipleChoiceField. Grazie!
Donturner,

1
Spirito simile:, for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.labelma mi piace di più il tuo metodo di costruzione.
jozxyqk,

21

È possibile utilizzare questo codice per aggiungere attr segnaposto per ogni campo TextInput nel modulo. Il testo per i segnaposto verrà preso dalle etichette dei campi del modello.

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

Ottima domanda Esistono tre soluzioni che conosco:

Soluzione n. 1

Sostituisci il widget predefinito.

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

Soluzione n. 2

Personalizza il widget predefinito. Se stai utilizzando lo stesso widget utilizzato di solito dal campo, puoi semplicemente personalizzarlo anziché crearne uno nuovo.

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

Soluzione n. 3

Infine, se stai lavorando con un modulo modello quindi ( oltre alle due precedenti soluzioni ) hai la possibilità di specificare un widget personalizzato per un campo impostando l' widgetsattributo della Metaclasse interna .

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

1
Stavo per scrivere una soluzione come la tua # 2. Vorrei aggiungere che è possibile applicare operazioni su tutti i campi ripetendo self.fields, ad esempio:for field_name in self.fields: self.fields[field_name].widget.attrs.update({"placeholder": sth})
Alberto Chiusole,

@AlbertoChiusole Sì, puoi, se è quello che vuoi fare. Grazie per segnalarlo.
Dwayne Crooks

@DwayneCrooks Ti suggerisco di aggiornare il tuo # 3 secondo la soluzione di cdosborn , perché è molto più breve e più leggibile.
Marian,

1

È indesiderabile dover sapere come creare un'istanza di un widget quando si desidera semplicemente sovrascriverne il segnaposto.

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

0

Il più delle volte desidero solo avere tutti i segnaposto uguali al nome dettagliato del campo definito nei miei modelli

Ho aggiunto un mixin per farlo facilmente in qualsiasi forma che creo,

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

E

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

Dopo aver esaminato il tuo metodo, ho usato questo metodo per risolverlo.

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
Si noti che il contenuto deve essere in inglese su Stack Overflow. A parte questo, questo sembra essere un post "anch'io", piuttosto che una risposta alla domanda posta sopra.
TylerH,

Direi che i post "anch'io" vanno bene se aggiungono maggiori dettagli. Che dire di questo approccio è diverso da uno qualsiasi degli altri? Qual è la tecnica o l'apprendimento essenziale qui?
halfer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.