在FormWizard中使用Django-sample-captcha一直出现"invalid captcha“错误

如题,在github上有作者对这个问题的回答,地址,不过略坑的是~问题是在两年前就提出来,然后作者最近才回答,无语了 。我也在issue里面提出了我的解决方法,ID就是allenling


查看了django的源码可知,FormWizard验证流程大概是下面这样子的:


处理post,验证

  A:验证通过,如果是最后一步,则就调用render_done方法。该方法是最后再验证的过程

如果不是最后一步~,则调用render_next_step方法,该方法是存储当前步骤验证过的数据,并且渲染下一步骤的模板和表单。

  B:验证不通过,则只是直接显示当前步骤的模板而已。


Django-sample-captcha验证码是直接使用

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

这样的方式来验证输入的验证码的。也就是说,一旦第一次验证之后,就删除了。而在FormWizard中 中会有一个 revalidate ,也就是二次验证的过程。所以才会在最后一步的时候引"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)




如果我们后台存储了验证码消息,并且还是引发了二次验证错误,我们就忽略这个错误,然后走的时候done方法。




你可能感兴趣的:(django,python,django,python,验证码)