0

I have a view function for login which blocks user after 3 unsuccessful login attempts

the function is as follows

def my_login(request):
  context = {}
  if request.method == 'POST':
    form = LoginForm(request.POST)
    user_id = form.cleaned_data['user_id']
    user_password = form.cleaned_data['password1']
    if form.is_valid:
      try:
        usr = Users.objects.get(pk=user_id)
      except:
        context['form'] = form
        context['msg'] = "User Not Found"
        return render(request, 'login.html', context)
      
      '''
      ## code for blocking 
      '''

      if user_password == usr.password1:
        usr.login_attempt = 0
        usr.save()
        login(usr)
        return redirect('dashbord')
      else:
        usr.login_attempt += 1
        usr.save()
        context['msg'] = f"Attempts tried { str(usr.login_attempt)}"
        form = LoginForm()
        context['form'] = form
  return render(request, 'login.html', context)
      

The problem here is when I entered wrong password it is rendering to login page but when I click on reload the form is again re submitting and the login_attempt getting updated

I don't want this kind of behavior so how can I stop form resubmitting on clicking reload

one possible solution I assumed is by manipulating the request object in the view like request = HttpRequest() but it is failing at csrf validation. is there any possibilities to overcome this issue

Premkumar
  • 23
  • 5

1 Answers1

0

You need to redirect to the same view after a successful form submission when the password is wrong, instead of re-rendering the view. You can pass a message by leveraging Django's messaging framework https://docs.djangoproject.com/en/dev/ref/contrib/messages/

from django.contrib import messages

    else:
        usr.login_attempt += 1
        usr.save()
        messages.warning(request, f"Attempts tried { str(usr.login_attempt)}")
        return redirect(reverse('login')) # or whatever your url is called

Then in your template something like this:

{% if messages %}
  {% for message in messages %}
    <p>{{ message }}</p>
  {% endfor %}
{% endif %}
Limecat
  • 401
  • 1
  • 4
  • thanks for the answer. and now I am with another issue of sending the form to the template `form = LoginForm(request.POST)` is there any other way for sending the form like mentioned above so that I can use form values to prefill the form in the display view? – Premkumar Nov 19 '21 at 07:10
  • @Premkumar I guess you want to have the same `user_id` pre-populated when the password was wrong? I guess one way would be storing the `user_id` as a session variable before redirecting, something like: `request.session['user_id']=user_id` Then when your view is being called again check if the variable is present with: `if 'user_id' in request.session: user_id=request.session['user_id']` Then use it as initial value for your form with `form = LoginForm(initial={'user_id': user_id})` You may have to first set `user_id=None` at the start so you won't get an error. – Limecat Nov 19 '21 at 10:10