2010-02-10 15 views
54

Ho un modulo con una proprietà di posta elettronica. Quando si usa {{}} form.email in caso di qualche errore di convalida, Django rende ancora il valore precedente nella attributo value del tag di ingresso:Valore di visualizzazione di un campo modulo django in un modello?

<input type="text" id="id_email" maxlength="75" class="required" value="[email protected]" name="email"> 

voglio rendere etichettare l'ingresso me (per aggiungere un po 'di javascript codice e una classe di errore in caso di errore). Per esempio, questo è il mio modello, invece di {{}} form.email:

<input type="text" autocomplete="on" id="id_email" name="email" class="email {% if form.email.errors %}error{% endif %}"> 

Tuttavia questo non visualizza il valore errorneous ("[email protected]" in questo esempio) per l'utente. Come si ottiene il valore del campo nel modello?

risposta

5

La soluzione proposta da Jens è corretta. Tuttavia, si scopre che se si inizializza il vostro ModelForm con una (esempio qui sotto) django istanza non popoleranno i dati:

def your_view(request): if request.method == 'POST': 
    form = UserDetailsForm(request.POST) 
    if form.is_valid(): 
     # some code here 
    else: 
     form = UserDetailsForm(instance=request.user) 

Così, ho fatto la mia classe di base ModelForm che popola i dati iniziali:

from django import forms 
class BaseModelForm(forms.ModelForm): 
    """ 
    Subclass of `forms.ModelForm` that makes sure the initial values 
    are present in the form data, so you don't have to send all old values 
    for the form to actually validate. 
    """ 
    def merge_from_initial(self): 
     filt = lambda v: v not in self.data.keys() 
     for field in filter(filt, getattr(self.Meta, 'fields',())): 
      self.data[field] = self.initial.get(field, None) 

Quindi, il semplice esempio vista si presenta così:

def your_view(request): if request.method == 'POST': 
    form = UserDetailsForm(request.POST) 
    if form.is_valid(): 
     # some code here 
    else: 
     form = UserDetailsForm(instance=request.user) 
     form.merge_from_initial() 
+0

Non vedo perché Django non lo stia facendo per impostazione predefinita ... Penso che invierò una patch e vedrò cosa ne penseranno le persone. –

0
{{form.fields.email}} 
+0

Questo dà:

+0

È possibile scrivere un filtra per recuperare il valore. – shanyu

+0

non esiste un modo integrato per ottenerlo? –

13

Ho una soluzione semplice per te!

{{ form.data.email }} 

Ho provato questo e ha funzionato. Ciò richiede che la tua vista compili la classe del form con i dati POST.

esempio molto semplice:

def your_view(request): 
    if request.method == 'POST': 
    form = YourForm(request.POST) 
    if form.is_valid(): 
     # some code here 
    else: 
    form = YourForm() 

    return render_to_response('template.html', {'form':form}) 

Speranza si può dire. Se avete domande per favore fatemelo sapere.

+0

I dati puliti non conterranno il campo email se non è stato possibile pulirlo durante la convalida. – shanyu

+0

Hai ragione. Non sarà possibile accedere a clean_data se is_valid() ha esito negativo. Sto cercando un'altra soluzione. – Jens

+0

Ho aggiornato il mio codice. C'era una soluzione semplice. Invece di clean_data usa semplicemente i dati. Funzionava anche se la convalida fallisce! I dati – Jens

11

questo sembra funzionare.

{{ form.fields.email.initial }} 
+3

Questo è quello che ha funzionato per me. – PKKid

+7

Potrei sbagliarmi, ma credo che mostrerà il valore iniziale ogni volta. Ad esempio, prova ad inviare il modulo in modo da generare un errore e vedrai che il modulo che ricarica l'errore avrà di nuovo il valore iniziale, non il valore che l'utente ha inserito prima di aver generato l'errore. – mlissner

1

Se hai popolato il modulo con un'istanza e non con i dati POST (come la risposta suggerita richiede), è possibile accedere ai dati utilizzando {{}} form.instance.my_field_name.

36

Si può fare questo dal modello con qualcosa di simile:

{% if form.instance.some_field %} 
     {{form.instance.some_field}} 
{% else %} 
     {{form.data.some_field}} 
{% endif %} 

Ciò visualizzerà il valore di istanza (se il modulo viene creato con un esempio, è possibile utilizzare iniziale, invece, se volete), o altrimenti visualizza i dati POST come quando si verifica un errore di convalida.

+2

una vergogna questa risposta è sepolto così in profondità! Questo è il modo di farlo senza aggiungere alcun codice al tuo progetto o applicare patch al tuo Django. –

+1

Puoi approfondire ciò che sto compilando in quei campi inventati? Ho provato alcune varianti e non ha funzionato. – jordaninternets

5

{{}} form.field_name.value funziona per me

+0

dipende dalla versione. Funziona in Django 1.3. Nuova funzionalità: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.BoundField.value – mlissner

2

ho voluto per visualizzare il valore di un campo formset. Ho concluso questa soluzione, che dovrebbe funzionare per forme normali anche:

{% if form.email.data %} {{ form.email.data }} 
{% else %} {{ form.initial.email }} 
{% endif %} 

Le soluzioni precedenti non hanno funzionato molto bene per me, e dubito avrebbero lavorato in caso di forme prefissati (ad esempio assistenti e formsets) . Le soluzioni che utilizzano {{ form.data.email }} non possono funzionare, perché si tratta di una ricerca nel dizionario e con i moduli con prefisso il nome del campo sarebbe simile a "1-email" (modulo wizard e prefisso) o "form-1-email" (formset) e il segno meno (-) non è consentito nelle espressioni di ricerca modello punteggiato.

{{form.field_name.value}} è solo Django 1.3+.

99

Questa era una richiesta di funzionalità che è stata corretta in Django 1.3.

Ecco l'errore: https://code.djangoproject.com/ticket/10427

In sostanza, se si sta eseguendo qualcosa dopo 1.3, nei modelli di Django si può fare:

{{ form.field.value|default_if_none:"" }} 

O in Jinja2:

{{ form.field.value()|default("") }} 

Nota che field.value() è un metodo, ma nei modelli di Django gli () sono omessi, mentre nel metodo Jinja2 le chiamate sono esplicite.

Se vuoi sapere quale versione di Django stai usando, ti dirà quando esegui il comando runserver.

Se siete su qualcosa prima di 1.3, probabilmente si può utilizzare la correzione postato nel suddetto bug: https://code.djangoproject.com/ticket/10427#comment:24

+0

Questa è la risposta giusta per Django> = 1.3. Questo era evidentemente assente dalla documentazione di django, ma ora sembra essere stato corretto (almeno nella versione dev). https://code.djangoproject.com/ticket/16851 – zlovelady

+17

Questo ha il brutto effetto che se 'form.field.value' è' None', allora verrà visualizzato il testo "None". Per visualizzare invece una stringa vuota, usa '{{form.field.value | default_if_none:" "}}' – cberzan

+0

+1 per menzionare questo funziona solo in> = 1.3. Sono ancora in esecuzione 1.2, e non riuscivo a capire perché non funzionava fino a quando non ho letto questo. – Wipqozn

0

ho provato alcune delle possibilità citate, e questo è come ho risolto il mio problema:

#forms.py 
class EditProfileForm(forms.ModelForm): 
    first_name = forms.CharField(label='First Name', 
           widget=forms.TextInput(
           attrs={'class': 'form-control'}), 
           required=False) 
    last_name = forms.CharField(label='Last Name', 
           widget=forms.TextInput(
           attrs={'class': 'form-control'}), 
           required=False) 
    # username = forms.CharField(widget=forms.TextInput(
    #        attrs={'class': 'form-control'}), 
    #        required=True) 
    address = forms.CharField(max_length=255, widget=forms.TextInput(
           attrs={'class': 'form-control'}), 
           required=False) 
    phoneNumber = forms.CharField(max_length=11, 
           widget=forms.TextInput(
           attrs={'class': 'form-control'}), 
           required=False) 
    photo = forms.ImageField(label='Change Profile Image', required=False) 

    class Meta: 
     model = User 
     fields = ['photo', 'first_name', 'last_name', 'phoneNumber', 'address'] 
        # 'username', 



#views.py 
def edit_user_profile(request, username): 
    user = request.user 
    username = User.objects.get(username=username) 
    user_extended_photo = UserExtended.objects.get(user=user.id) 
    form = EditProfileForm(request.POST or None, request.FILES, instance=user) 
    user_extended = UserExtended.objects.get(user=user) 
    if request.method == 'POST': 
     if form.is_valid(): 
      # photo = UserExtended(photo=request.FILES['photo'] or None,) 
      user.first_name = request.POST['first_name'] 
      user.last_name = request.POST['last_name'] 
      user_extended.address = request.POST['address'] 
      user_extended.phoneNumber = request.POST['phoneNumber'] 
      user_extended.photo = form.cleaned_data["photo"] 
      # username = request.POST['username'] 
      user_extended.save() 
      user.save() 

      context = { 
       'form': form, 
       'username': username, 
       'user_extended_photo': user_extended_photo, 
      } 

      return render(request, 'accounts/profile_updated.html', context) 
    else: 
     photo = user_extended.photo 
     first_name = user.first_name 
     last_name = user.last_name 
     address = user_extended.address 
     phoneNumber = user_extended.phoneNumber 
     form = EditProfileForm(
      initial={'first_name': first_name, 'last_name': last_name, 
            'address': address, 'phoneNumber': phoneNumber, 
            'photo': photo}) 
    context = { 
     'form': form, 
     'username': username, 
     'user_extended_photo': user_extended_photo, 

    } 
    return render_to_response('accounts/edit_profile.html', context, 
           context_instance=RequestContext(request)) 

#edit_profile.html 
    <form action="/accounts/{{ user.username }}/edit_profile/" method="post" enctype='multipart/form-data'> 
            {% csrf_token %} 
             <div class="col-md-6"> 
              <div class="form-group"> 
               {{ form.as_p }} 
              </div> 
             </div> 
            <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> 
            <button type="submit" value="Update Profile" class="btn btn-info btn-fill pull-right">Update Profile</button> 
            <div class="clearfix"></div> 
           </form> 

che sto cercando di spiegare questo in un modo così che i principianti possono trovare più facile da capire. Prestare particolare attenzione alla else:

 photo = user_extended.photo 
     first_name = user.first_name 
     last_name = user.last_name 
     address = user_extended.address 
     phoneNumber = user_extended.phoneNumber 
     form = EditProfileForm(
      initial={'first_name': first_name, 'last_name': last_name, 
            'address': address, 'phoneNumber': phoneNumber, 
            'photo': photo}) 

E 'quello che ottiene l'attrib valore, ad es:

<p><label for="id_first_name">First Name:</label> <input class="form-control" id="id_first_name" name="first_name" type="text" value="Emmanuel" /></p> 
<p><label for="id_last_name">Last Name:</label> <input class="form-control" id="id_last_name" name="last_name" type="text" value="Castor" /></p> 
Problemi correlati