Как сделать так, чтобы капча появлялась только после неудачной попытки авторизации
Я использую django-simple-captcha в своем приложении, хочу освоить методы работы с ней.
Возникла следующая проблема: Хочу сделать так, чтобы она, на странице входа в аккаунт, появлялась только после неудачной попытки входа.
Форма капчи выглядит так:
class CaptchaForm(forms.Form):
captcha = CaptchaField(
label=('')
)
Views login:
class UserLogin(View):
def get(self, request):
form = LoginForm()
return render(
request, 'users/login.html', context={'form': form}
)
def post(self, request):
if request.method == 'POST':
bound_form = LoginForm(request.POST)
if bound_form.is_valid():
cd = bound_form.cleaned_data
user = authenticate(
request, email=cd['email'], password=cd['password']
)
if user is not None:
if user.is_active:
login(request,user)
messages.success(request, 'Вы успешно вошли в систему!')
return redirect('mainsite:dashboard')
else:
return HttpResponse('Disabled account')
else:
messages.error(
request, 'Неверный адрес электронной почты или пароль'
)
return redirect('users:login')
else:
bound_form = LoginForm()
return render(
request, 'users/login.html', context={'form': bound_form}
)
Если сделать капчу не отдельной формой, а просто запихнуть поле капчи в форму логина, то она будет отображаться сразу, в этом случае не понятно, как можно реализовать эту идею(появление поля после неудачного входа)
Я пытался сделать две формы входа, одну с капчей другую без и в представлении выводить используя флаг, но тогда код получается совсем не DRYа это не есть хорошо.
Ответы (1 шт):
Решение:
Я решил использовать в данной ситуации джанго сессии.
Мне пришлось использовать две формы логина,в одной форме содержится поле для капчи,в другой - нет. Т.к если сделать отдельную форму для капчи, в представлении приходится делать в разы больше условий и получается больше строчек кода, а результат не меняется.
Код с решением:
Views.py:
def get(self, request):
#если попыток входа не было вообще
if 'try_login' not in request.session:
#создаем ключ try_login со значением false
request.session['try_login'] = False
check_try_login = request.session['try_login']
#обрабатываем форму без капчи
form = LoginForm()
#если попытка входа уже была
else:
#запоминаем значение в переменную
check_try_login = request.session['try_login']
if not check_try_login:
# Если попытки входа не было, но сессия try_login есть,
# то отображаем форму без капчи
form = LoginForm()
else:
# Если попытка входа была, то отображаем форму с капчей
form = SecureLoginForm()
return render(
request, 'users/login.html', context={'form': form}
)
def post(self, request):
if request.method == 'POST':
# запоминаем значение try_login в переменную
check_try_login = request.session['try_login']
if not check_try_login:
# Если попытки входа не было, то проверяем и отправляем форму
# в которой нет поля капчи
bound_form = LoginForm(request.POST)
if bound_form.is_valid():
cd = bound_form.cleaned_data
user = authenticate(
request, email=cd['email'], password=cd['password']
)
if user is not None:
if user.is_active:
login(request,user)
messages.success(request, 'Вы успешно вошли в систему!')
del request.session['try_login']
return redirect('mainsite:dashboard')
else:
return HttpResponse('Disabled account')
else:
messages.error(
request, 'Неверный ввод данных'
)
request.session['try_login'] = True
return redirect('users:login')
# Если попытка входа была, то проверяем и отправляем форму
# в которой есть поле капчи
else:
bound_form = SecureLoginForm(request.POST)
if bound_form.is_valid():
cd = bound_form.cleaned_data
user = authenticate(
request, email=cd['email'], password=cd['password']
)
else:
# если введеная капча не проходит проверку, то
# сбрасываем все введенные данные и вызываем ошибку
messages.error(
request, 'Неверный ввод данных'
)
return redirect('users:login')
if user is not None:
if user.is_active:
login(request,user)
messages.success(
request,
'Вы успешно вошли в систему!'
)
del request.session['try_login']
return redirect('mainsite:dashboard')
else:
return HttpResponse('Disabled account')
else:
messages.error(
request, 'Неверный ввод данных'
)
# Если введенные данные пользователя не проходят проверку,
# то запоминаем попытку входа, и сбрасываем все введенные
# данные
request.session['try_login'] = True
return redirect('users:login')
else:
bound_form = SecureLoginForm()
return render(
request, 'users/login.html', context={
'form': bound_form,
}
)
forms.py:
class LoginForm(forms.Form):
email = forms.EmailField(
label=('Email'),
widget=forms.EmailInput(attrs={'class': 'form-control'}),
)
password = forms.CharField(
label=('Пароль'),
strip=False,
widget=forms.PasswordInput(attrs={'class': 'form-control'}),
)
class Meta(object):
model = CustomUser
fields = [
'email', 'password'
]
class SecureLoginForm(forms.Form):
email = forms.EmailField(
label=('Email'),
widget=forms.EmailInput(attrs={'class': 'form-control'}),
)
password = forms.CharField(
label=('Пароль'),
strip=False,
widget=forms.PasswordInput(attrs={'class': 'form-control'}),
)
captcha = CaptchaField(
label=(''),
)
class Meta(object):
model = CustomUser
fields = [
'email', 'password', 'captcha'
]
P.S Код получился совсем не DRY, и как это исправить, для меня пока что не понятно, но он решает данную проблему.