2010-10-15 12 views
11

Ich habe einen FormWizard, wo ich Daten aus dem ersten Formular an den Konstruktor des zweiten Formulars übergeben muss, damit ich ein dynamisches Formular erstellen kann.Wie Sie vorherige Formulardaten an den Konstruktor einer DynamicForm in FormWizard übergeben

Ich kann die Daten des ersten Formulars über den Process_step des FormWizard abrufen.

Ich erstelle die Felder der zweiten Form mit einem Datenbankaufruf der Liste der Felder.

class ConditionWizardDynamicQuestions(forms.Form): 

    def __init__(self, DynamicQuestions=None, *args, **kwargs): 
     super(ConditionWizardDynamicQuestions, self).__init__(*args, **kwargs) 
     questions = Question.objects.filter(MYDATA = DATA_FROM_1STFORM) 
     for q in questions: 
      dynField = FieldFactory(q) 
      self.fields[q.label] = dynField 

Wie kann ich übergehen die DATA_FROM_1STFORM?


meines resultierenden Code: gab ich die die Form init, und schaltete es auf jeden Fall zu den CreateQuestions. Dann nutzte der Assistent get_form override, um das Formular nach der Erstellung zu ändern.

Antwort

5

FormWizard übergibt bereits die Daten von jedem vorherigen Formular an das nächste Formular. Wenn Sie diese Daten abrufen möchten, um eine Klasse zu instanziieren (beispielsweise wenn ein Formular spezielle Schlüsselwortargumente benötigt), können Sie das Querydict durch Überschreiben von get_form in Ihrer Formularassistentenklasse beheben. Zum Beispiel:

class SomeFormWizard(FormWizard): 
    def get_form(self, step, data=None): 
     if step == 1 and data: # change this to whatever step requires 
           # the extra data 
      extra_data = data.get('key_from_querydict') 
      if extra_data: 
       return self.form_list[step](data, 
              keyword_argument=extra_data, 
              prefix=self.prefix_for_step(step),                                    
              initial=self.initial.get(step, None)) 
     # Fallback for the other forms. 
     return self.form_list[step](data, 
            prefix=self.prefix_for_step(step),                                    
            initial=self.initial.get(step, None)) 

Beachten Sie, dass Sie auch parse_params(self, request, *args, **kwargs) in FormWizard außer Kraft setzen können die URL/Anforderungsdaten zugreifen zu können, wie würden Sie in einer Ansicht, wenn Sie also Anforderungsdaten haben (request.user, zum Beispiel), dass wird Um für alle Formulare benötigt zu werden, ist es besser, die Daten von dort zu beziehen.

Hoffe, das hilft.

+0

Ich stehe auf ein Problem beim Weiterleiten von Daten von Schritt 1 zu Schritt 3, aber Ihre Lösung ist hilfreich und aufschlussreich. – BozoJoe

+0

Mit welchem ​​Problem stößt du? AFAIK sollte es Ihnen Zugriff auf alle Daten aus allen vorherigen Formularen ermöglichen - das heißt, Schritt 3 sollte die Daten aus Schritt 1 und Schritt 2 haben. –

+0

mein Problem war ich versuchte, Initiale aus dem Assistenten zu verwenden und überschreiben die Formulare __drin__. Ich habe die get_form benutzt und die Welt wird klarer für mich :) – BozoJoe

0

Ich arbeitete vor kurzem mit django Formular-Assistenten, und ich löste das ähnliche Problem. Ich glaube nicht, dass Sie Daten an init, aber passieren kann, was Sie tun können, ist die init Konstruktor überschreiben:

next_form = self.form_list[1] 

# let's change the __init__ 
# function which will set the choices :P 
def __init__(self, *args, **kw): 
    super(next_form, self).__init__(*args, **kw) 
    self.fields['availability'].choices = ... 
next_form.__init__ = __init__ 

Es ist ziemlich ärgerlich, dass in Python Sie können eine nicht deklarieren und zuweisen Funktion in einem Schritt und muss es in den Namespace setzen (es sei denn, Sie verwenden Lambdas), aber na ja.

+0

Ich bin mir nicht sicher, ob ich folgen. Überschreibt dieser Code das __init__ des unterordneten FormWizard? Wie kann ich die Daten von Schritt1 bis Schritt2 bekommen? – BozoJoe

+0

nein, überschreibt es das __init__ des nächsten Formulars. Beachten Sie, wie es heißt: self.fields ['availability']. Choices = ..., jetzt anstelle von ... können Sie beliebige Daten setzen, die Sie passieren wollen –

+0

Ich habe bereits die "next_form" __init__ überschrieben, also habe ich immer noch ' Sehen Sie, wie Sie Daten aus dem vorherigen Formular des Assistenten übergeben. – BozoJoe

8

Ich löste dies durch Überschreiben von get_form_kwargs für das WizardView. Normalerweise gibt es nur ein leeres Dictionary zurück, das get_form auffüllt. Wenn Sie es also überschreiben, um ein Dictionary mit den Daten zurückzugeben, die Sie zuvor gefüllt haben, können Sie kwargs an Ihr Formular init übergeben.

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 

Dann in Ihrem Formular init Methode können Sie nur Pop die kwarg vor dem Aufruf von Super-off:

self.your_data = kwargs.pop('client', None) 
3

Aufschalten der get_form_kwargs Methode des Formulars Assistenten in Aussicht

Ansicht. py

class FormWizard(SessionWizardView): 
    def get_form_kwargs(self, step=None): 
     kwargs = {} 
     if step == '1': 
      step0_form_field = self.get_cleaned_data_for_step('0')['previous_form_field_data'] 
      kwargs.update({'step0_form_field': step0_form_field}) 
     return kwargs 

Überschreiben Sie die Init von Ihnen r formieren Sie die Daten aus dem vorherigen Feld, um ein dynamisches Feld zu erstellen.

forms.py

class MyForm(forms.Form): 
    #some fields 

class MyForm1(forms.Form): 
    def __init__(self, *args, **kwargs): 
     extra = kwargs.pop('step0_form_field') 
     super(MyForm1, self).__init__(*args, **kwargs) 

     for i in range(extra): 
      self.fields['name_%s' % i] = forms.CharField()