2010-10-15 11 views
11

Ho un FormWizard in cui ho bisogno di dati dal primo modulo per passare al costruttore del secondo modulo in modo da poter creare un modulo dinamico.Come passare i dati del modulo precedente al costruttore di un DynamicForm in FormWizard

È possibile ottenere i dati del primo modulo tramite process_step di FormWizard.

Creo i campi del secondo modulo con una chiamata al database dell'elenco di campi.

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 

Come posso passare sopra il DATA_FROM_1STFORM?


mio codice risultante: ho abbandonato il init della forma, e acceso agli CreateQuestions def. Quindi ha utilizzato la sovrascrittura get_form della procedura guidata per modificare la forma dopo la creazione.

class ConditionWizard(SessionFormWizard): 
    def get_form(self, request, storage, step=None, data=None, files=None): 
     form = super(ConditionWizard, self).get_form(request, storage, step, data, files) 
     stepIndex = self.get_step_index(request, storage, step) 
     if stepIndex == 1: 
      form.CreateQuestions(request.session["WizardConditionId"]) 
     if stepIndex == 3: 
      form.fields['hiddenConditionId'].initial = request.session["WizardConditionId"] 
      form.fields['medicationName'].queryset = Medication.objects.filter(condition = request.session["WizardConditionId"]) 
     return form 

risposta

5

FormWizard passa già i dati da ogni modulo precedente al modulo successivo. Se si desidera ottenere tali dati per creare un'istanza di una classe (ad esempio, se un modulo ha argomenti di parole chiave speciali che richiede), è possibile afferrare il testo di query sostituendo get_form nella classe della procedura guidata del modulo. Per esempio:

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)) 

Nota che si può anche ignorare parse_params(self, request, *args, **kwargs) in FormWizard per accedere ai dati url/richiesta, proprio come si farebbe in una vista, quindi, se si dispone di dati richiesta (request.user, per esempio) che sta andando per essere necessario per tutte le forme, potrebbe essere meglio ottenere i dati da lì.

Spero che questo aiuti.

+0

Sto incontrando un problema nel passaggio dei dati dal passaggio 1 al passaggio 3, ma la soluzione è utile e intuitiva. – BozoJoe

+0

Che tipo di problema stai incontrando? AFAIK dovrebbe consentire di accedere a tutti i dati di tutti i moduli precedenti, ovvero il passaggio 3 dovrebbe avere i dati del passaggio 1 e del passaggio 2. –

+0

il mio problema era che stavo tentando di utilizzare l'iniziale dalla procedura guidata e sovrascrivere il modulo __dentro__. Sono passato a utilizzare get_form e il mondo è diventato più chiaro per me :) – BozoJoe

0

Recentemente stavo lavorando con il form wizard di django e stavo risolvendo il problema simile. Io non credo che si possa passare i dati al init, tuttavia, che cosa si può fare, è eseguire l'override del init costruttore:

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__ 

E 'abbastanza fastidioso che in python non è possibile dichiarare e assegnare un funzione in un colpo solo e metterlo nello spazio dei nomi (a meno che non si usi lambda), ma vabbè.

+0

non sono sicuro io seguo. Questo codice ha la precedenza su __init__ della creazione guidata della sottoclasse? Come mi consente di ottenere i dati dal passaggio 1 al passaggio 2? – BozoJoe

+0

no, sostituisce __init__ del modulo successivo. Si noti come dice self.fields ['availability']. Choices = ..., ora invece di ... puoi inserire tutti i dati che vuoi passare –

+0

Ho già overrided il "next_form" __init__, quindi continuo a don ' Per vedere come passano i dati dalla forma precedente della procedura guidata. – BozoJoe

8

Ho risolto questo annullando get_form_kwargs per il WizardView. Solitamente restituisce un dizionario vuoto che popola get_form, quindi sovrascrivendolo per restituire un dizionario con i dati che hai bisogno di prepopolare, puoi passare kwargs al tuo modulo 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 

Poi, nella tua forma init metodo si può semplicemente pop il kwarg off prima di chiamare super:

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

l'override del metodo get_form_kwargs del mago forma in vista

vista. 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 

Override l'init di voi r forma spuntando i dati ottenuti dal campo precedente per creare un campo dinamico.

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() 
Problemi correlati