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.