Как передать данные предыдущей формы конструктору DynamicForm в FormWizard - PullRequest
11 голосов
/ 15 октября 2010

У меня есть FormWizard, в котором мне нужны данные из первой формы для передачи в конструктор второй формы, чтобы я мог построить динамическую форму.

Я могу получить данные первой формы с помощью process_step FormWizard.

Я создаю поля второй формы с помощью вызова базы данных из списка полей.

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

Как я могу передать DATA_FROM_1STFORM ?


мой результирующий код: Я отказался от init формы и переключил его на определение CreateQuestions. Затем с помощью переопределения мастера get_form измените форму после создания.

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

Ответы [ 4 ]

8 голосов
/ 22 октября 2012

Я решил это, переопределив get_form_kwargs для WizardView. Обычно он просто возвращает пустой словарь, который заполняет get_form, поэтому переопределив его, чтобы вернуть словарь с предварительно заполненными данными, вы можете передать kwargs в форму 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

Затем в вашей форме init метод вы можете просто вытолкнуть kwarg перед вызовом super:

self.your_data = kwargs.pop('client', None)
5 голосов
/ 11 ноября 2010

FormWizard уже передает данные из каждой предыдущей формы в следующую форму. Если вы хотите получить эти данные для создания экземпляра класса (например, если у формы есть специальные ключевые аргументы, которые ей требуются), один из способов сделать это - получить запрос, переопределив get_form в вашем классе мастера форм. Например:

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

Обратите внимание, что вы также можете переопределить parse_params(self, request, *args, **kwargs) в FormWizard для доступа к данным URL / запроса, так же, как вы делаете это в представлении, поэтому, если у вас есть данные запроса (например, request.user), которые будут необходимы для всех форм было бы лучше получить данные оттуда.

Надеюсь, это поможет.

3 голосов
/ 28 августа 2013

Переопределить метод get_form_kwargs вашего мастера форм в представлениях

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

Переопределить инициализацию вашей формы, выдавая данные, полученные из предыдущего поля, чтобы создатьдинамическое поле.

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()
0 голосов
/ 17 октября 2010

Я недавно работал с мастером форм django и решал аналогичную проблему. Я не думаю, что вы можете передавать данные в init , однако вы можете переопределить конструктор init :

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__

Довольно досадно, что в python вы не можете объявить и назначить функцию за один раз и поместить ее в пространство имен (если вы не используете лямбда-выражения), ну да ладно.

...