Hardik Jain
Hardik Jain

Reputation: 21

Unable to Redirect to Next Page After Successful Login in Django

Despite entering the correct credentials, I am consistently redirected back to the login page instead of being granted access to the Products page. This issue persists even though the credentials are valid, which suggests that there might be a problem with the login and authentication process. As a result, I am unable to proceed beyond the login page.

Views.py

from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, Http404
from .forms import UserRegisterForm, UserLoginForm,Reviews_Form
from django.contrib import messages
from .models import UserRegister, Review
from django.contrib.auth import authenticate, login ,logout
from django.contrib.auth.decorators import login_required
from urllib.parse import urlparse
from django.urls import is_valid_path

# Create your views here.

products = [
    {
        "slug": "Mustang-GT",
        "About": """The Ford Mustang GT in its stunning white color is nothing short of a modern-day classic. From the moment you lay eyes on 
        it, the Mustang's sleek and muscular design commands attention and admiration. The pristine white finish only adds to its allure, 
        giving it a timeless, elegant look that stands out on the road. Performance: Under the hood, the Mustang GT roars to life with its 
        5.0-liter V8 engine, delivering a thrilling 450 horsepower. The acceleration is exhilarating, and the handling is precise, making 
        every drive a memorable experience. Whether you're cruising down the highway or taking on winding roads, the Mustang GT's performance
        is unmatched in its class. Interior: Step inside, and you're greeted with a blend of classic muscle car ambiance and modern 
        sophistication. The leather seats are comfortable and supportive, perfect for long drives. The dashboard is well-designed,
        with intuitive controls and a high-quality infotainment system that keeps you connected and entertained. Driving Experience: 
        Driving the Mustang GT is an absolute joy. The sound of the engine is music to any car enthusiast's ears, and the responsive 
        steering makes you feel in complete control. The car's suspension strikes a perfect balance between comfort and sportiness, 
        ensuring a smooth ride even on less-than-perfect roads. Conclusion: The Ford Mustang GT in white is a perfect blend of beauty,
        power, and sophistication. It's a car that not only performs exceptionally well but also turns heads wherever it goes. 
        Whether you're a long-time Mustang fan or new to the world of muscle cars, this vehicle will exceed your expectations. 
        Highly recommended for anyone looking for a thrilling and stylish driving experience.""",
        "image": "images/car.jpg"
    }
]

def Home(request):
    return render(request, "home.html")

def SignUp(request):
    if request.method == "POST":
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form_info = UserRegister(
                username=form.cleaned_data.get('username'),
                email=form.cleaned_data.get('email'),
                password=form.cleaned_data.get('password1')
            )
            form_info.save()
            
            messages.success(request, 'Your account has been created!')
            return HttpResponseRedirect('/Products')
        else:
            print("Form is not valid")
            print(form.errors)
    else:
        form = UserRegisterForm()
    return render(request, 'SignUp.html', {'form': form})

@login_required
def Products(request):
    return render(request, "products.html")

@login_required
def about_product(request, slug):
    product = None
    for item in products:
        if item["slug"] == slug:
            product = item
            break
    if product is None:
        raise Http404("Product not found")

    if request.method == 'POST':
        form =Reviews_Form(request.POST)
        if form.is_valid():
            form_save=form.save(commit=False)
            form_save.User=request.user
            form_save.save()
            messages.success(request, "Your review has been submitted!")
            print("Review done :",form_save.Review)
            return HttpResponseRedirect(f'/Products/{slug}')
        else:
            form = Reviews_Form()
    else:
        form = Reviews_Form()
   
    return render(request, "about_product.html", {"product": product,'form':form})

def Login(request):
    next_url = request.GET.get('next', '/Products')
    if request.method == "POST":
        form = UserLoginForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username').strip()
            password = form.cleaned_data.get('password')
            user = authenticate(request, username=username, password=password)
            if user is not None:
                print("Authentication successful for user:", user.username)
                login(request, user)
                print("User is authenticated:", get_user(request).is_authenticated)
                next_url = request.POST.get('next', next_url)
                parsed_url = urlparse(next_url)
                print("next url:", next_url)
                print("Parsed URL netloc:", parsed_url.netloc)
                print("Is valid path:", is_valid_path(next_url))

                if not parsed_url.netloc and is_valid_path(next_url):
                    print('Next URL is valid, redirecting...')
                    return HttpResponseRedirect(next_url)
                else:
                    print('Next URL is invalid or external, redirecting to /Products')
                return HttpResponseRedirect('/Products')
            else:
                print("Authentication failed")
                messages.error(request, "Invalid username or password")
                form.add_error(None, "Invalid username or password")

        else:
            messages.error(request, "Please fix the errors below.")
            print("Form errors:", form.errors)
            print("Non-field errors:", form.non_field_errors())
            for field in form:
                print(f"Field Error: {field.name} - {field.errors}")
    else:
        form = UserLoginForm()
    return render(request, "Login.html", {'form': form, 'next': next_url})

def Logout(request):
    if request.user.is_authenticated:
        logout(request)
        messages.success(request,'Logout Successful')
    else:
        messages.info(request, 'You are not logged in.')
    return HttpResponseRedirect('/Home')

Urls.py

from django.urls import path
from . import views

urlpatterns=[path("Home",views.Home),
             path("SignUp",views.SignUp,name='signup'),
             path("Products",views.Products,name="Products"),
             path('Products/<slug:slug>',views.about_product,name="About Product"),
             path("login",views.Login,name='login'),
             path('logout',views.logout,name='logout')]

login.html

{% extends "base.html" %}

{% block title %}
Login
{% endblock %}

{% load static %}

{% block css_files %}
<link rel="stylesheet" href="{% static 'reviews/Login.css' %}">
{% endblock %}

{% block content %}

    {% if next %}
        <form action="{% url 'login' %}?next={{ next }}" method="POST" >
    {%else%}
        <form method="POST" action="{% url 'login' %}">
    {% endif %}

        {% csrf_token %}
        <div class="input-section">
            
            {% if form.non_field_errors %}
                <div class="error-message">
                    {% for error in form.non_field_errors %}
                        <p>{{ error }}</p>
                    {% endfor %}
                </div>
            {% endif %}
            
            <div class="input-group">
                <label for="{{ form.username.id_for_label }}">Username</label>
                {{ form.username }}
                {% if form.username.errors %}
                    <div class="error-message">
                        {% for error in form.username.errors %}
                            <p>{{ error }}</p>
                        {% endfor %}
                    </div>
                {% endif %}
            </div>

            <div class="input-group">
                <label for="{{ form.password.id_for_label }}">Password</label>
                {{ form.password }}
                {% if form.password.errors %}
                    <div class="error-message">
                        {% for error in form.password.errors %}
                            <p>{{ error }}</p>
                        {% endfor %}
                    </div>
                {% endif %}
            </div>
            <button class="submit-btn" type="submit">Login</button>
        </div>
    </form>
{% endblock %}

settings.py

"""
Django settings for Feedback project.

Generated by 'django-admin startproject' using Django 5.1.1.

For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-q(_7*_7qv0h!v*0ug*wbr2dazv062dlgun@c=uamc)l38z59u1'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'reviews',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'Feedback.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR /"reviews"/"templates"/"reviews"],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Feedback.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/5.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',  
    'reviews.backends.CustomAuthBackend',    
]



LOGIN_URL = '/login'
LOGIN_REDIRECT_URL = '/Products'

Upvotes: 2

Views: 75

Answers (1)

Nicxzmiller Marcus
Nicxzmiller Marcus

Reputation: 43

Djangos authentication system makes use of the built-in USER model which can be imported from django.contrib.auth.models.User. But in your sign Up function, you are saving credentials manually in a custom model UserRegister without hashing the password. Your current function saves the password as text.

form_info = UserRegister(
    username=form.cleaned_data.get('username'),
    email=form.cleaned_data.get('email'),
    password=form.cleaned_data.get('password1')  # ❌ Password should be hashed
)
form_info.save()

Then in your login function, you are using authenticate() which only works if the user exists in the Django's default User model. Django’s authenticate() won't recognize your custom UserRegister.

I would advice you make use of the built-in User model as that would correctly handle authentication.

from django.contrib.auth.models import User  # Import Django's built-in User model

def SignUp(request):
    if request.method == "POST":
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = User.objects.create_user(
                username=form.cleaned_data.get('username'),
                email=form.cleaned_data.get('email'),
                password=form.cleaned_data.get('password1')  # ✅ Password is now hashed
            )
            user.save()
            messages.success(request, 'Your account has been created!')
            return HttpResponseRedirect('/Products')
        else:
            print("Form is not valid")
            print(form.errors)
    else:
        form = UserRegisterForm()
    return render(request, 'SignUp.html', {'form': form})

Also, for the custom UserRegister, extend Django's built-in AbstractUser

from django.contrib.auth.models import AbstractUser

class UserRegister(AbstractUser):
    pass  # Use Django's built-in authentication fields

Upvotes: 1

Related Questions