django передать аргумент из вида в форму только один раз - PullRequest
0 голосов
/ 26 февраля 2020

У меня есть механизм генератора OTP, благодаря которому в методе GET генерируется уникальный 4-точечный OTP, который отправляется в OTPAuthenticationForm () следующим образом:

views.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")

forms.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")

Как генерируемый_отчет должен быть передан только один раз в OTPAuthForm (), чтобы его можно было проверить по пользовательскому вводу OTP (OTP, полученному по электронной почте).

Метод clean () не вызывается; вместо этого при выполнении form.is_valid (), форма возвращает 'недопустимая' ошибка

Обновление: OTPAuthenticationForm (forms.Form) ранее импортировал класс AuthenticationForm (), который требуются поля имени пользователя, пароля и настраиваемое поле OTP.

Именно поэтому form.is_valid () возвращался как недействительный, поскольку имя пользователя, пароль auth обрабатывались в приложении отдельно.

1 Ответ

0 голосов
/ 26 февраля 2020

Я думаю, вы не должны передавать otp в GET запрос, вместо этого он должен выполнить POST request:

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

Теперь вопрос заключается в том, как сохранить этот OTP при получении запроса POST. Вы можете использовать сессию. Как это:

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
        ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...