2010-11-04 12 views
147

Prendi questo modulo molto semplice per esempio.Come aggiungo un segnaposto su un CharField in Django?

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

questo viene reso nel modello:

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

Tuttavia, voglio aggiungere la 'segnaposto' attribuire a questo campo con un valore di "Ricerca" in modo che il codice HTML sarebbe simile :

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

Preferibilmente Vorrei passare il valore segnaposto per CharField nella classe del form tramite un dizionario o qualcosa di simile:

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

Quale sarebbe il modo migliore per realizzare questo?

risposta

212

Vedere widgets documentation. In sostanza si sarebbe simile:

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

Più scrittura, sì, ma la separazione tiene conto la migliore astrazione dei casi più complicati.

È possibile anche dichiarare un attributo widgets contenente una mappatura <field name> => <widget instance> direttamente sul Meta del vostro ModelForm sottoclasse.

+6

come si farebbe su un modello? –

+0

hai bisogno di specificare 'forms.TextInput' per fare la dichiarazione di' attrs = {'placeholder': 'Cerca'} '? – JhovaniC

+1

@OvedD, so che questo è vecchio, ma vedi questa domanda: http://stackoverflow.com/questions/4341739/adding-an-attribute-to-the-input-tag-for-a-django-modelform-field – Simon

19

È possibile utilizzare questo codice per aggiungere il segnaposto attr per ogni campo TextInput nel proprio 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 
43

Per un ModelForm, è possibile utilizzare la classe di Meta in tal 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'}), 
     } 
+0

Nota che in questo caso non puoi specificare il campo in il corpo della classe. –

+0

Questo era il metodo più semplice per me - ed era bello che tutti gli altri attributi (cioè richiesti) fossero ancora aggiunti automaticamente senza che io dovessi specificarli. – JxAxMxIxN

28

Gli altri metodi sono tutti buoni. Tuttavia, se si preferisce non specificare il campo (ad esempio, per un certo 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 protected]' 

Esso consente di utilizzare i segnaposto per dipendono dal istanza per ModelForms con istanza specificata.

+6

Questo è ottimo perché evita di dover duplicare la lunga istanziazione dei widget per oggetti più complicati come 'ModelMultipleChoiceField'. Grazie! – donturner

+1

Spirito simile: 'per f in MyCommentForm.base_fields.values ​​(): f.widget.attrs [" placeholder "] = f.label', ma mi piace il tuo metodo di costruzione migliore. – jozxyqk

+0

Questa è la migliore risposta. – kloddant

8

Ottima domanda. Ci sono tre soluzioni che so di:

Soluzione N ° 1

Sostituire il widget di default.

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

Soluzione # 2

personalizzare il widget di default. Se si utilizza lo stesso widget utilizzato solitamente dal campo, è possibile personalizzarlo semplicemente anziché creare un'istanza completamente nuova.

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 # 3

Infine, se si sta lavorando con un modulo tipo allora (oltre alle due soluzioni precedenti) si ha la possibilità di specificare un widget personalizzato per una campo impostando l'attributo widgets della classe interna Meta.

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 le operazioni su tutti i campi ripetendo su 'self.fields', ad es .:' per nome_campo in self.fields: self.fields [nome_campo] .widget.attrs.update ({" segnaposto ": sth})' –

+0

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

Problemi correlati