Django FormWizard如何动态更改form_list

发布于 2021-01-29 15:20:57

我能够动态调用一种与我从步骤ierier中选择的数据相关的表格

但是当我使用该done方法时,我可以看到myform_list保持不变。

这是我所做的:

def get_form_list(request, form_list=None):
    if form_list is None:
        form_list = [ProviderForm, DummyForm, ConsummerForm, DummyForm, \
                 ServicesDescriptionForm]
    return UserServiceWizard.as_view(form_list=form_list)(request)


class UserServiceWizard(SessionWizardView):
    instance = None

    def __init__(self, **kwargs):
        self.form_list = kwargs.pop('form_list')
        return super(UserServiceWizard, self).__init__(**kwargs)

    def get_form_instance(self, step):
        if self.instance is None:
            self.instance = UserService()
        return self.instance

    def get_context_data(self, form, **kwargs):
        data = self.get_cleaned_data_for_step(self.get_prev_step(
                                                    self.steps.current))
        if self.steps.current == '1':
            service_name = str(data['provider']).split('Service')[1]
            form = class_for_name('th_' + service_name.lower() + '.forms',
                                  service_name + 'ProviderForm')
            self.form_list['1'] = form #here my form is correctly change I can see

        elif self.steps.current == '3':
            service_name = str(data['consummer']).split('Service')[1]
            form = class_for_name('th_' + service_name.lower() + '.forms',
                                  service_name + 'ConsummerForm')
            self.form_list['3'] = form

        context = super(UserServiceWizard, self).get_context_data(form=form,
                                                              **kwargs)
        return context


    def done(self, form_list, **kwargs):
        print self.form_list #here form_list contains ProviderForm, DummyForm, ConsummerForm, DummyForm, ServicesDescriptionForm

在步骤0,我的form_list可以:

{u'0': <class 'django_th.forms.wizard.ProviderForm'>, 
u'1': <class 'django_th.forms.wizard.DummyForm'>, 
u'2': <class 'django_th.forms.wizard.ConsummerForm'>, 
u'3': <class 'django_th.forms.wizard.DummyForm'>, 
u'4': <class 'django_th.forms.base.ServicesDescriptionForm'>}

在第1步,我的form_list正常:我们可以看到第二个表单是我期望的表单

{u'0': <class 'django_th.forms.wizard.ProviderForm'>, 
u'1': <class 'th_rss.forms.RssProviderForm'>, 
u'2': <class 'django_th.forms.wizard.ConsummerForm'>, 
u'3': <class 'django_th.forms.wizard.DummyForm'>, 
u'4': <class 'django_th.forms.base.ServicesDescriptionForm'>}

在步骤2中,我的form_list是ko;与步骤0相同:我的第二个表单返回到DummyForm

{u'0': <class 'django_th.forms.wizard.ProviderForm'>, 
u'1': <class 'django_th.forms.wizard.DummyForm'>, 
u'2': <class 'django_th.forms.wizard.ConsummerForm'>,
u'3': <class 'django_th.forms.wizard.DummyForm'>, 
u'4': <class 'django_th.forms.base.ServicesDescriptionForm'>}

我该如何更改self.form_list并保留所做的更改,get_context_data直到向导结束而不是在每个步骤中都没有?

*这里的 *编辑 是完整的代码,可以很好地满足Rohan的建议:

def get_form(self, step=None, data=None, files=None):
    """
        change the form instance dynamically from the data we entered
        at the previous step
    """
    if step is None:
        step = self.steps.current

    if step == '1':
        # change the form
        prev_data = self.get_cleaned_data_for_step('0')
        service_name = str(prev_data['provider']).split('Service')[1]
        class_name = 'th_' + service_name.lower() + '.forms'
        form_name = service_name + 'ProviderForm'
        form_class = class_for_name(class_name, form_name)
        form = form_class(data)
    elif step == '3':
        # change the form
        prev_data = self.get_cleaned_data_for_step('2')
        service_name = str(prev_data['consummer']).split('Service')[1]
        class_name = 'th_' + service_name.lower() + '.forms'
        form_name = service_name + 'ConsummerForm'
        form_class = class_for_name(class_name, form_name)
        form = form_class(data)
    else:
        # get the default form
        form = super(UserServiceWizard, self).get_form(step, data, files)
    return form

def done(self, form_list, **kwargs):
    """
        Save info to the DB
        The process is :
        1) get the infos for the Trigger from step 0, 2, 4
        2) save it to TriggerService
        3) get the infos from the "Provider" and "Consummer" services
        at step 1 and 3
        4) save all of them
    """
    # get the datas from the form for TriggerService
    i = 0
    for form in form_list:
        # cleaning
        data = form.cleaned_data
        # get the service we selected at step 0 : provider
        if i == 0:
            trigger_provider = UserService.objects.get(
                name=data['provider'],
                user=self.request.user)
            model_provider = get_service_model('provider', data)
        # get the service we selected at step 2 : consummer
        elif i == 2:
            trigger_consummer = UserService.objects.get(
                name=data['consummer'],
                user=self.request.user)
            model_consummer = get_service_model('consummer', data)
        # get the description we gave for the trigger
        elif i == 4:
            trigger_description = data['description']
        i += 1

    # save the trigger
    trigger = TriggerService(
        provider=trigger_provider, consummer=trigger_consummer,
        user=self.request.user, status=True,
        description=trigger_description)
    trigger.save()

    model_fields = {}
    # get the datas from the form for Service related
    # save the related models to provider and consummer
    i = 0
    for form in form_list:
        model_fields = {}
        data = form.cleaned_data
        # get the data for the provider service
        if i == 1:
            for field in data:
                model_fields.update({field: data[field]})
            model_fields.update({'trigger_id': trigger.id, 'status': True})
            model_provider.objects.create(**model_fields)
        # get the data for the consummer service
        elif i == 3:
            for field in data:
                model_fields.update({field: data[field]})
            model_fields.update({'trigger_id': trigger.id, 'status': True})
            model_consummer.objects.create(**model_fields)
        i += 1

    return HttpResponseRedirect('/')
关注者
0
被浏览
37
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    get_context_data()我认为,更合适的get_form()方法是在向导视图中实现方法,并根据步骤和先前的数据返回不同的表单实例,而不是更改中的表单列表等。

    像这样:

    class UserServiceWizard(SessionWizardView):
        instance = None
    
        def get_form(self, step=None, data=None, files=None):
            if step is None:
                step = self.steps.current
    
            prev_data = self.get_cleaned_data_for_step(self.get_prev_step(
                                                        self.steps.current))
            if step == '1':
                service_name = str(prev_data['provider']).split('Service')[1]
                form_class = class_for_name('th_' + service_name.lower() + '.forms',
                                      service_name + 'ProviderForm')
                form = form_class(data)
            elif step == '3':
                service_name = str(prev_data['consummer']).split('Service')[1]
                form_class = class_for_name('th_' + service_name.lower() + '.forms',
                                      service_name + 'ConsummerForm')
                form = form_class(data)
            else:
                form = super(UserServiceWizard, self).get_form(step, data, files)
    
            return form
    

    这里的技巧是不更改表单列表的长度(您已正确完成),而只是更改表单实例。Djangoget_form()为此提供了重写方法的方法。Django将采用此方法,并始终使用它来获取该方法的表单实例。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看