动态表单的Django Formwizard不会进行下一步 [英] Django Formwizard with dynamic form does not proceed to next step

查看:167
本文介绍了动态表单的Django Formwizard不会进行下一步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个django formwizard,其中第一个表单在运行时生成了一个选择字段。我可以使用正确的选择生成表单,但是当我单击提交时,formwizard不会继续进行下一步。它提交表单,但返回form1。这是我的表单和视图

  ##表单
class EventForm1(forms.Form):
def __init __(self,* args,** kwargs):
##在运行时获取选项
choices = kwargs.pop('loan_choices',[])
super(EventForm1,self)。 __init __(* args,** kwargs)
self.fields ['loan'] = forms.ChoiceField(choices = choices,required = False,widget = forms.Select(attrs = {'class':'events_loan_name' ,'event_attribute':'loan','name':'loan'}))
attribute_to_change = forms.ChoiceField(choices = [('monthly_payment','Monthly Payment'),('interest_rate'价格')],widget = forms.Select(attrs = {'class':'attribute_to_change','name':'attribute_to_change','event_attribute':'attribute_to_change'}))

class EventForm2 (forms.Form):
start_date = forms.DateField(widget = forms.TextInput(attrs = {'class':'event_dates','start_date':'start_date','na我'':'event_start_date','event_attribute':'start_date'}))

##视图
类EventFormWizard(SessionWizardView):
事件

def done(self,form_list,** kwargs):
self.finalize_new_event(form_list)
return HttpResponseRedirect('/')

def get_form(self,step = None,data = None,files = None):
form = super(EventFormWizard,self).get_form(step,data,files)

#确定步骤如果没有给出
如果步骤为无:
step = self.steps.current

打印(步骤,表单)
如果step == 0:
loan_sessions = self.request.session.get('loan_sessions',无)
如果loan_sessions!=无:
loan_sessions = pickle.loads(self.request.session [' loan_sessions'])
else:
loan_sessions = []

loan_choices = []
在loan_session中的loan_session:
loan_choice =(loan_session ['number'],loan_session ['name'])
loan_choices.append(loan_choice)

##更新选择
form = EventForm1(loan_choices = loan_choices)

返回形式

def finalize_new_loan(self,form_list):
添加一个自动属性到新的贷款,将其保存到loan_sessions并从会话中删除新的贷款对象

表单中的form_list:
cleaning_data = form.cleaned_data
打印(clean_data)

我正在使用django 1.8和form-tools包。 >

解决方案

我发现发生了什么。表单向导的post方法调用get_form,如下所示:

 #获取当前步骤的表单
form = self。 get_form(data = self.request.POST,files = self.request.FILES)

print(form.is_valid(),form.errors,form.is_bound)
#并尝试验证
如果form.is_valid():
#如果表单有效,请存储清除的数据和文件。
self.storage.set_step_data(self.steps.current,
self.process_step(form))
self.storage.set_step_files(self.steps.current,
self.process_step_files (form))

#检查当前步骤是最后一步
如果self.steps.current == self.steps.last:
#没有更多的步骤,渲染完成视图
return self.render_done(form,** kwargs)
else:
#转到下一步
返回self.render_next_step(form)
return self 。$ {$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $

如果当前窗体验证,它只调用下一步的窗体,是因为我的自定义get_form钩子在创建动态窗体时不检查POST数据。无论如何,这里是工作的自定义get_form钩子:

  def get_form(self,step = None,data = None,files = None) :
form = super(EventFormWizard,self).get_form(step,data,files)

#确定步骤,如果没有给出
如果步骤为无:
step = self.steps.current

如果step ==0:
loan_sessions = self.request.session.get('loan_sessions',无)
如果loan_sessions! =无:
loan_sessions = pickle.loads(self.request.session ['loan_sessions'])
else:
loan_sessions = []

loan_choices = []
在loan_session中的loan_session:
loan_choice =(loan_session ['number'],loan_session ['name'])
loan_choices.append(loan_choice)

##在启动表单时传递数据,即POST
##数据如果如果表单向导
##在render_done方法中再次验证此表单,则在post
##或self.storage.get_step_data(form_key)期间调用gets_form函数
form = EventForm1( loan_choices = loan_choices,data = data)

返回表单


I am trying to create a django formwizard where the first form has a choicefield generated at runtime. I can generate the form with the correct choices but when I click submit the formwizard does not proceed to the next step. It submits the form but returns to form1. Here are my forms and view

##Forms
class EventForm1(forms.Form):
    def __init__(self, *args, **kwargs):
        ##Get choices at runtime
        choices = kwargs.pop('loan_choices', [])
        super(EventForm1, self).__init__(*args, **kwargs)
        self.fields['loan'] = forms.ChoiceField(choices=choices, required=False, widget=forms.Select(attrs={'class':'events_loan_name', 'event_attribute':'loan', 'name':'loan'}) )
    attribute_to_change = forms.ChoiceField(choices=[('monthly_payment','Monthly Payment'), ('interest_rate','Interest Rate')], widget=forms.Select(attrs={'class': 'attribute_to_change', 'name':'attribute_to_change', 'event_attribute':'attribute_to_change'}))

class EventForm2(forms.Form):
    start_date = forms.DateField(widget=forms.TextInput(attrs={'class': 'event_dates','start_date':'start_date', 'name':'event_start_date', 'event_attribute':'start_date'}))

##Views
class EventFormWizard(SessionWizardView):
    """Form wizard for adding an event"""

    def done(self, form_list, **kwargs):
        self.finalize_new_event(form_list)
        return HttpResponseRedirect('/')

    def get_form(self, step=None, data=None, files=None):
        form = super(EventFormWizard, self).get_form(step, data, files)

        # determine the step if not given
        if step is None:
            step = self.steps.current

        print(step, form)
        if step == "0":
            loan_sessions = self.request.session.get('loan_sessions', None)
            if loan_sessions != None:
                loan_sessions = pickle.loads(self.request.session['loan_sessions'])
            else:
                loan_sessions = []

            loan_choices = []
            for loan_session in loan_sessions:
                loan_choice = (loan_session['number'], loan_session['name'])
                loan_choices.append(loan_choice)

            ##Update the choices for the select 
            form = EventForm1(loan_choices=loan_choices)

        return form

    def finalize_new_loan(self, form_list):
        """Adds a autmatic properties to the new loan, saves it to the loan_sessions and deletes the new loan object from the session"""

        for form in form_list:
            cleaned_data = form.cleaned_data
            print(cleaned_data)

I'm using django 1.8 with the form-tools package.

解决方案

I discovered what's going on. The form wizard's post method calls get_form like so:

        # get the form for the current step
        form = self.get_form(data=self.request.POST, files=self.request.FILES)

        print(form.is_valid(), form.errors, form.is_bound)
        # and try to validate
        if form.is_valid():
            # if the form is valid, store the cleaned data and files.
            self.storage.set_step_data(self.steps.current,
                                       self.process_step(form))
            self.storage.set_step_files(self.steps.current,
                                        self.process_step_files(form))

            # check if the current step is the last step
            if self.steps.current == self.steps.last:
                # no more steps, render done view
                return self.render_done(form, **kwargs)
            else:
                # proceed to the next step
                return self.render_next_step(form)
        return self.render(form)

It only calls the next step's form if the current form validates, which it never does because my custom get_form hook doesn't check for the POST data when creating the dynamic form. Anyway here is the working custom get_form hook:

    def get_form(self, step=None, data=None, files=None):
        form = super(EventFormWizard, self).get_form(step, data, files)

        # determine the step if not given
        if step is None:
            step = self.steps.current

        if step == "0":
            loan_sessions = self.request.session.get('loan_sessions', None)
            if loan_sessions != None:
                loan_sessions = pickle.loads(self.request.session['loan_sessions'])
            else:
                loan_sessions = []

            loan_choices = []
            for loan_session in loan_sessions:
                loan_choice = (loan_session['number'], loan_session['name'])
                loan_choices.append(loan_choice)

            ##Pass the data when initing the form, which is the POST
            ## data if the got_form function called during a post
            ## or the self.storage.get_step_data(form_key) if the form wizard
            ## is validating this form again in the render_done method
            form = EventForm1(loan_choices=loan_choices, data=data)

        return form

这篇关于动态表单的Django Formwizard不会进行下一步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆