2009-08-07 12 views
7

Próbuję utworzyć prosty wielostronicowy formularz Django przy użyciu FormWizard. Formularz powinien być następujący:Zdobądź wcześniej wprowadzone informacje w Django FormWizard

  1. Pozwól odwiedzającemu wpisać imię i nazwisko w formularzu.
  2. Przejdź do następnej strony, na której wyświetlone zostanie poprzednie imię i nazwisko, pojawi się również pole na tej stronie, na które użytkownik wpisze wiadomość.
  3. Wizistor zostanie przeniesiony na stronę Django done.html, gdzie wszystkie informacje będą przechowywane i wyświetlane.

W kroku 2 mam problemy z określeniem sposobu wyświetlania informacji wprowadzonych przez odwiedzającego w kroku 1. Zamieszczam kod formularzy i dwóch szablonów używanych w kroku 1 i 2 poniżej :

forms.py

from django import forms 
from django.shortcuts import render_to_response 
from django.contrib.formtools.wizard import FormWizard 

class ContactWizard(FormWizard): 
    def done(self, request, form_list): 
     return render_to_response('done.html', { 
      'form_data': [form.cleaned_data for form in form_list], 
     }) 

    def get_template(self, step): 
     return 'buydomain/templates/reg%s.html' % step 

class Form1(forms.Form): 
    firstName = forms.CharField() 
    lastName = forms.CharField() 

class Form2(forms.Form): 
    message = forms.CharField(widget=forms.Textarea) 

szablonu krok 1:

{% block content %} 
<p>Step {{ step }} of {{ step_count }}</p> 
<form action="." method="post"> 
<table> 
{{ form }} 
</table> 
<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> 
{{ previous_fields|safe }} 
<input type="submit"> 
</form> 
{% endblock %} 

szablon do kroku 2:

{% block content %} 
<p>Step {{ step }} of {{ step_count }}</p> 


{% comment %} 
Show values entered into Form1 here ! 
{% endcomment %} 

<form action="." method="post"> 
<table> 
{{ form }} 
</table> 
<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> 
{{ previous_fields|safe }} 
<input type="submit"> 
</form> 
{% endblock %} 

Przepraszam, jeśli nie mam pewności co do tego, co chcę osiągnąć i mam nadzieję, że ktoś dostarczy rozwiązanie. Z góry dziękuję.

Odpowiedz

6

Najpierw ogólna porada - jeśli nie wiesz, jak używać czegoś w Django, wyciągnij edytor tekstu i spójrz na kod. Nie zawsze jest to najszybszy sposób, aby uzyskać odpowiedź, ale uważam, że na dłuższą metę opłaca ona dywidendy.

Spróbuj dodać extra_context do drugiego kroku, zastępując process_step w podklasie FormWizard. Oto komentarze od wewnątrz FormWizard (django 1.1):

def process_step(self, request, form, step): 
     """ 
     Hook for modifying the FormWizard's internal state, given a fully 
     validated Form object. The Form is guaranteed to have clean, valid 
     data. 

     This method should *not* modify any of that data. Rather, it might want 
     to set self.extra_context or dynamically alter self.form_list, based on 
     previously submitted forms. 

     Note that this method is called every time a page is rendered for *all* 
     submitted steps. 
     """ 
     pass 

więc w swojej własnej klasy ContactWizard, coś jak (Uwaga: I nie uruchomić tego):

class ContactWizard(FormWizard): 
    def process_step(self,request,form,step): 
     if step == 1: 
      self.extra_context = {'whatever': form.whatever_you_want_from_the_form} 
      return 
     else: 
      return 
+2

jaki sposób późniejszego dostępu klasa forma dane extra_context? – BozoJoe

+0

'extra_context' jest przekazywane przez' FormWizard' do szablonu do renderowania. –

+0

Nadal przegłosowałem tę odpowiedź, ale chciałem poinformować innych, że od django 1.4 podpis metody process_step został zmieniony na tylko przekazać w obiekcie formularza. Jak stwierdził @bpoetz, proszę usiąść z dokumentami i przeczytać je, aby znaleźć rozwiązanie, które będzie pasować do twoich potrzeb. – avelis

3

nie wiem jeśli nadal warto opublikować to rozwiązanie. Niemniej jednak. Potrzebne rzeczy między różnymi formularzami (krokami) używanymi przez Kreatora, są łatwo dostępne, kiedy dajesz kreatorowi dodatkowe atrybut w postaci dyktatu. Tak:

class WizardRegistration(FormWizard): 
    def __init__(self, *args, **kwargs): 
     super(WizardRegistration, self).__init__(*args, **kwargs) 

     setattr(self, 'chosen', {}) 

pomiędzy etapami można następnie łatwo przybierać formę lub modelu rzeczy i przechowywać je aż done() metoda dojdziesz. Przechowywać wartość formularz

self.chosen['something_to_store'] = form.cleaned_data.get('a_form_value') 

Albo nawet dostać/zmiana/zapisać model:

object = Model.objects.get('some_query') 

if self.chosen['object']: 
    self.chosen['object'].string = 'Something stringy' 
    self.chosen['object'].save() 
4
odpowiedź

Toby Panzer za nie pozwala klasa formularz aby uzyskać dostęp do dodatkowych danych kontekstowe - tylko szablon formularz jest wyświetlany na ma dostęp. To powiedziawszy, brzmi to jak prawdopodobnie to, czego potrzebujesz. Jednakże, jeśli potrzebujesz formularza, aby uzyskać dostęp, rozwiązałem to przez przesłanianie get_form_kwargs. Zwykle po prostu zwraca pusty słownik, który wypełnia get_form, więc przez przesłanianie go w celu zwrócenia słownika z danymi, które są wstępnie wypełnione, możesz przekazać kwargs do formy init.

def get_form_kwargs(self, step=None): 
    kwargs = {} 
    if step == '1': 
     your_data = self.get_cleaned_data_for_step('0')['your_data'] 
     kwargs.update({'your_data': your_data,}) 
    return kwargs 

Następnie w formularzu startowych metodzie można po prostu pop kwarg off przed wywołaniem Super:

self.your_data = kwargs.pop('client', None) 
Powiązane problemy