Py学习  »  Django

django只将参数从视图传递到窗体一次

Simran • 5 年前 • 1953 次点击  

我有一个OTP生成器机制,在GET方法中,生成一个唯一的4-dit OTP,并将其发送到OTPAuthenticationForm(),如下所示:

视图.py

if request.method == 'GET':
   otp = 'abcd'
   # code to send otp via mail
   form = OTPAuthenticationForm(request=request, otp=otp) # this is how the OTP is passed only once.
   return ....
elif request.method == 'POST':
    form = OTPAuthenticationForm(request.POST, request=request)
    if form.is_valid():                 # the clean_field() method is not invoked/throws error.
       print("OTP is valid")
    else: 
       print("OTP is invalid")

表单.py

from django.contrib.auth.forms import AuthenticationForm


class OTPAuthenticationForm(AuthenticationForm):
    otp = forms.CharField(required=True, widget=forms.TextInput)

    def __init__(self, otp, *args, **kwargs):
       self.otp = kwargs.pop("otp")

       super(OTPAuthenticationForm, self).__init__(*args, **kwargs)

    def clean(self):
       if self.otp!= self.cleaned_data['otp']:
          raise forms.ValidationError("Invalid OTP")

如何将生成的otp只传递一次给OTPAuthForm(),以便根据用户输入otp(通过电子邮件接收的otp)对其进行验证。

更新: OTPAuthenticationForm(forms.Form) 之前导入的类AuthenticationForm()需要用户名、密码字段和自定义OTP字段。

这就是为什么form.is_valid()返回为无效,因为在应用程序中分别处理用户名、密码身份验证。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/56589
文章 [ 1 ]  |  最新文章 5 年前
ruddra
Reply   •   1 楼
ruddra    5 年前

我认为你不应该通过 otp GET 相反,请求应该由 POST 请求:

form = OTPAuthenticationForm(request.POST, request=request, otp=otp)

class OTPAuthenticationForm(AuthenticationForm):
    otp = forms.CharField(required=True, widget=forms.TextInput)

    def __init__(self, otp, *args, **kwargs):
       self.otp_value = kwargs.pop("otp", None)
       super(OTPAuthenticationForm, self).__init__(*args, **kwargs)

    def clean(self):
       otp = self.cleaned_data['otp']
       if self.otp_value != otp:
          raise forms.ValidationError("Invalid OTP")
       return super(OTPAuthenticationForm, self).clean()

现在,问题是当您收到POST请求时如何存储这个OTP。你可以使用会话。这样地:

if request.method == 'GET':
   otp = 'abcd'
   form = OTPAuthenticationForm(request=request)
   request.session['otp'] = otp  # storing data in session
   return ....
elif request.method == 'POST':
    form = OTPAuthenticationForm(request.POST, request=request, otp=request.session.get('otp'))
    if form.is_valid():
        del request.session['otp'] # deleting data in session
        ...