使用Django SessionWizardView时遇RecursionError:递归深度超出的解决方法
解决Django SessionWizardView调用get_cleaned_data_for_step触发的递归错误
问题场景
在继承SessionWizardView的ProfileUser视图中,为步骤3编写条件判断函数check_type_user_master时,调用self.get_cleaned_data_for_step('0')触发了RecursionError: maximum recursion depth exceeded错误。相关代码如下:
# view.py 代码 class ProfileUser(LoginRequiredMixin, SessionWizardView): file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'files')) login_url = 'login' template_name = 'gyms/profile.html' STEP_ONE, STEP_TWO, STEP_THREE, STEP_FOUR = '0', '1', '2', '3' def check_type_user_master(self): data = self.get_cleaned_data_for_step('0') print(data) if data.get('type_user') == 'M': return True return False def return_true(self): return True condition_dict = { STEP_ONE: return_true, STEP_TWO: return_true, STEP_THREE: check_type_user_master, } form_list = [ (STEP_ONE, FormLocationStepOne), (STEP_TWO, ChoiceTypeUser), (STEP_THREE, FormMasterStepTwo), ] def done(self, form_list, **kwargs): return render(self.request, 'done.html', { 'form_data': [form.cleaned_data for form in form_list], })
错误原因
get_cleaned_data_for_step方法内部会调用条件判断函数验证步骤可用性,而你的条件函数check_type_user_master又反过来调用get_cleaned_data_for_step,形成循环递归调用,最终触发递归深度超限错误。
解决方案
方案1:直接从Session获取原始数据
绕开get_cleaned_data_for_step,直接从存储中读取步骤0的原始数据:
def check_type_user_master(self): # 从storage中获取步骤0的原始提交数据 step0_data = self.storage.get_step_data(self.STEP_ONE) # 注意键名格式:表单类名小写-字段名,需根据你的FormLocationStepOne实际字段调整 type_user = step0_data.get('form_locationstepone-type_user') return type_user == 'M'
方案2:手动实例化表单获取清洗后的数据
如果需要验证数据合法性并获取清洗后的值,可手动实例化表单:
def check_type_user_master(self): step0_data = self.storage.get_step_data(self.STEP_ONE) form = FormLocationStepOne(step0_data) if form.is_valid(): return form.cleaned_data.get('type_user') == 'M' return False
额外修正:条件函数的绑定问题
原代码中condition_dict直接引用类方法会导致绑定错误,需改为实例方法引用:
# 方式1:在初始化方法中绑定实例方法 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.condition_dict = { self.STEP_ONE: self.return_true, self.STEP_TWO: self.return_true, self.STEP_THREE: self.check_type_user_master, } # 方式2:用lambda包裹确保绑定实例 condition_dict = { STEP_ONE: lambda self: self.return_true(), STEP_TWO: lambda self: self.return_true(), STEP_THREE: lambda self: self.check_type_user_master(), }
内容的提问来源于stack exchange,提问作者AliReza7222
相关产品推荐
相关产品推荐

