如题,在github上有作者对这个问题的回答,地址,不过略坑的是~问题是在两年前就提出来,然后作者最近才回答,无语了 。我也在issue里面提出了我的解决方法,ID就是allenling
查看了django的源码可知,FormWizard验证流程大概是下面这样子的:
处理post,验证
A:验证通过,如果是最后一步,则就调用render_done方法。该方法是最后再验证的过程
如果不是最后一步~,则调用render_next_step方法,该方法是存储当前步骤验证过的数据,并且渲染下一步骤的模板和表单。
B:验证不通过,则只是直接显示当前步骤的模板而已。
try:
CaptchaStore.objects.get(response=response, hashkey=value[0], expiration__gt=get_safe_now()).delete()
except CaptchaStore.DoesNotExist:
raise ValidationError(getattr(self, 'error_messages', {}).get('invalid', ugettext_lazy('Invalid CAPTCHA')))
无论你是在哪一步使用Django-sample-captcha,到最后render_done方法中总是会有二次验证的。
在github上,作者表示因为不知道调用字段的clean()方法是否是被django的form调用还是被formwizard调用,所以不确定是否应该在第一次验证后是否删除掉验证码。并且,一直留着验证码的危险的,并不建议大家关掉删除数据库中的验证这个步骤。
同时,他还给出了一个解决方法,或许可以在CaptchaStore中加入一个计数器,当计数器为0的时候,删除数据库中的验证码,我们可以在formwizard中设置这个计数器为2,这样,验证码就不会在第一次验证的时候被删除掉了,并且也能保证验证码最后一定被删除掉。
我觉得吧,也可以这么弄:
二次验证错误是render_done方法中引发的,在render_done方法中会对每一个form的数据再进行验证~这个时候由于captcha删掉了验证码,so,引发了二次验证错误,就会转到render_revalidation_failure这个方法中,该方法中,处理也是只是简单的显示当前模板了~跟在post中,第一次验证错误一样,只不过,post中的第一次验证错误是不会把数据存在后台的。
但是:我们知道,在form wizard中,一旦对form验证成功后~就会把验证号的数据保存在你使用的后台存储中,Session或者Cookie。比如,使用Session,我们有
我们可以看到,验证成功后会保存有验证码的,如果在第一次的时候就验证不通过,也就是说一开始输入的就是错误的验证码,后台是不会存有验证码数据的
所以嘛。我们只需要在
render_revalidation_failure里面查看Sessoin/Cookie里面是否存在我们的captcha数据就OK了,如果是输入不正确~放心~根本走不到该方法。其实主要是查看self.storage里面的东西:
def render_revalidation_failure(self, step, form, **kwargs):
if step == 'captcha':
if self.storage.get_step_data(step):
done_responses = self.done(self.get_form_list(), **kwargs)
self.storage.reset()
return done_responses
return super(ReUserWizard, self).render_revalidation_failure(step, form, **kwargs)