Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-forms

After refreshing page gives CSRF verification failed. Request aborted. error


This is image attached, CSRF verification failed. Request aborted.

When i refresh page after successfully login it ask for resubmit and when hit continue it shows "CSRF verification failed. Request aborted." error.

In login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
</head>
<body>
    Home

    {% if user.is_authenticated %}
        Hello {{name}} you are logged<br>
        <a href="{% url 'logout' %}">logout</a>
    {% else %}
    <form method="post">
    {% csrf_token %}
    {{form.as_p}}
    <button type="submit">login</button>
    {% endif %}
</form>
</body>
</html>

In views.py

from django.shortcuts import render, redirect
from login_app.forms import LoginForm, UserRegistrationForm
from django.contrib.auth import authenticate, login, logout
from django.middleware.csrf import get_token
from django.http import HttpResponseForbidden

# Create your views here.


def home(request):
    form = LoginForm()
    return render(request,'home.html',{'form':form})


def log_in(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        # if request.POST.get('csrfmiddlewaretoken') == get_token(request):
            # return HttpResponseForbidden('invalid')
        if form.is_valid():
            email = form.cleaned_data['email']
            password =  form.cleaned_data['password']
            try:
                user = authenticate(email = email,password=password)
                if user is None:
                    raise ValueError('not found')
                print(login(request,user))
                login(request,user)
                return render(request,'after.html',{'name':user})
                # return redirect('home')
            except ValueError as e:
                return redirect('home')
    else:
        form = LoginForm()
    return redirect('home')


def log_out(request):
    logout(request)
    return redirect('home')

In models.py

from typing import Any
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
from django.contrib.auth import authenticate

# Create your models here.

class CustomUserManager(UserManager):
    def _create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError("Email can not be empty")
        
        email = self.normalize_email(email)
        user = self.model(email = email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_user(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)
    
    def create_superuser(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff',True)
        extra_fields.setdefault('is_superuser', True)
        return self._create_user(email,password, **extra_fields)
    
class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(blank=True, default='',unique=True)
    phone_number = models.CharField(max_length=12,unique=True,blank=True,default='')
    password = models.CharField(max_length=200)
    name= models.CharField(max_length=255,blank=True,default='')

    is_active = models.BooleanField(default=True)
    is_superuser = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    date_joined = models.DateTimeField(auto_now_add=True)
    last_login = models.DateTimeField(blank=True, null=True)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = 'Custom User'
        verbose_name_plural = 'Custom Users'

    def get_full_name(self):
        return self.name
    
    def get_short_name(self):
        return self.name or self.email.split('@')[0]

In urls.py

from django.urls import path
from login_app.views import home, log_in, log_out

urlpatterns = [
    path("",home,name='home'),
    path("log_in",log_in,name='log_in'),
    path("log_out",log_out,name='log_out'),
]

In forms.py

from django import forms
from login_app.models import User

class LoginForm(forms.Form):
    email = forms.EmailField(label='Email',max_length=100)
    password = forms.CharField(label='Password',widget=forms.PasswordInput)


class UserRegistrationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ['phone_number','email','name','password']

I tried @csrf_exempt it works but i dont want to use as it is login form. I also looked for various solutions here but none of them worked.


Solution

  • I got solution for this. If we have submitted the form successfully, we don't want to resubmit the same. In order to prevent resubmission, we need to clear the form completely. We can use redirect(), instead of render(), and it won't throw CSRF error.

    This is the modified code:

    def user_login(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            try:
                user = User.validate_login(form.cleaned_data['email'],form.cleaned_data['password'])
                login(request, user)
                # user = user.get_full_name()
                user = User.objects.get(email = user)
                print(user.email)
                request.session['email'] = user.email
                request.session['name'] = user.name
                request.session['phone_number'] = user.phone_number
                request.session['img'] = user.pic.url
                print(user.phone_number,user.pic.url)
                ***return redirect('login')***
                # return render(request,'login.html',{'name':user,'csrf_token':get_token(request)})
            except ValueError as e:
                return redirect('login')
    form = LoginForm()
    if request.user.is_authenticated:
        img = request.session.get('img',None)
        return render(request,'login.html',{'img':img})
    return render(request,'login.html',{'form':form,'user':request.user})
    

    Below code was the issue:

    def log_in(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        # if request.POST.get('csrfmiddlewaretoken') == get_token(request):
            # return HttpResponseForbidden('invalid')
        if form.is_valid():
            email = form.cleaned_data['email']
            password =  form.cleaned_data['password']
            try:
                user = authenticate(email = email,password=password)
                if user is None:
                    raise ValueError('not found')
                print(login(request,user))
                login(request,user)
                ***return render(request,'after.html',{'name':user})***
                # return redirect('home')
            except ValueError as e:
                return redirect('home')
    else:
        form = LoginForm()
    return redirect('home')