Question :
I am using a custom login template to login to staff or non-staff members but the login page only allows the staff members to login in. When I try to log in using a non-staff member the page stays on the login page but when I log in with a superuser email it redirects to the blog page URL.
One thing before you give me the answer, Yes I have already added
AUTH_USER_MODEL = "accounts.Account"
LOGIN_REDIRECT_URL = "blogs"
LOGOUT_REDIRECT_URL = "blogs"
urls.py
from django.urls import path
from .views import CustomLogoutView, CustomRegistrationView, CustomLoginView
urlpatterns = [
path("register/", CustomRegistrationView.as_view(), name="register"),
path("login/", CustomLoginView.as_view(), name="login"),
path("logout/", CustomLogoutView.as_view(), name="logout"),
]
views.py
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import reverse_lazy
from django.views.generic import CreateView
from accounts.models import Account
from .forms import CustomRegistrationForm, CustomLoginForm
class CustomRegistrationView(CreateView):
model = Account
form_class = CustomRegistrationForm
success_url = reverse_lazy("login")
redirect_authenticated_user = True
template_name: str = "accounts/register.html"
success_message = "You registered successfully."
class CustomLoginView(LoginView):
model = Account
form_class = CustomLoginForm
redirect_authenticated_user: bool = True
success_url = reverse_lazy("dashboard")
template_name: str = "accounts/login.html"
class CustomLogoutView(LogoutView):
template_name: str = "accounts/logout.html"
next_page = None
manager.py
from django.contrib.auth.models import BaseUserManager
class UserManager(BaseUserManager):
def create_user(
self, email, first_name, last_name, roll_no, password, department=None
):
if not email:
raise ValueError("User requires an Email")
if not first_name:
raise ValueError("User requires a First name")
if not roll_no:
raise ValueError("User requires a Roll Number")
user = self.model(
email=self.normalize_email(email),
first_name=first_name,
last_name=last_name,
roll_no=roll_no,
department=department,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, first_name, last_name, password, department="OT"):
if not email:
raise ValueError("Admin requires an Email")
if not first_name:
raise ValueError("Admin requires a First name")
user = self.model(
email=self.normalize_email(email),
first_name=first_name,
last_name=last_name,
department=department,
is_staff=True,
is_admin=True,
is_superadmin=True,
is_active=True,
roll_number=None,
)
user.set_password(password)
user.save(using=self._db)
return user
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.utils.translation import gettext_lazy as _
from .manager import UserManager
# AbstractUser can also be used because it already have some predefined model fields
# and we can add more if we want to.
class Account(AbstractBaseUser):
# choices for departement
class Department(models.TextChoices):
CSE = "CSE", "COMPUTER SCIENCE"
IT = "IT", "INFORMATION TECHNOLOGY"
EE = "EE", "ELECTRIC ENGINEERING"
CE = "CE", "CIVIL ENGINEERING"
TE = "TE", "TEXTILE ENGINEERING"
ME = "ME", "MECHANICAL ENGINEERING"
OT = "OT", "OTHER"
username = None
email = models.EmailField(max_length=100, unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
roll_number = models.PositiveIntegerField(unique=True, null=True, blank=True)
profile_picture = models.ImageField(upload_to="photos/profiles", blank=True)
bio = models.TextField(null=True, blank=True)
department = models.CharField(
max_length=30,
choices=Department.choices,
blank=True,
null=True,
)
# required
date_joined = models.DateTimeField(auto_now=True)
last_login = models.DateTimeField(auto_now_add=True)
is_admin = models.BooleanField(default=False)
is_superadmin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
USERNAME_FIELD: str = "email"
REQUIRED_FIELDS = [
"first_name",
"last_name",
]
objects = UserManager()
def __str__(self) -> str:
if self.roll_number and self.first_name:
return "{} - {}".format(self.email, self.roll_number)
else:
return self.email
# must add in
def get_profile_image_filename(self):
return str(self.profile_picture)[
str(self.profile_picture).index(f"photos/profiles/{self.pk}/")
]
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
form.py
from django import forms
from django import forms
from django.contrib.auth.forms import (
UserCreationForm,
AuthenticationForm,
)
from .models import Account
class CustomRegistrationForm(UserCreationForm):
# DEPARTMENT_CHOICES = [
# ("CSE", "COMPUTER SCIENCE"),
# ("IT", "INFORMATION TECHNOLOGY"),
# ("EE", "ELECTRIC ENGINEERING"),
# ("CE", "CIVIL ENGINEERING"),
# ("TE", "TEXTILE ENGINEERING"),
# ("ME", "MECHANICAL ENGINEERING"),
# ("OT", "OTHER"),
# ]
email = forms.EmailField(
max_length=100,
required=True,
widget=forms.TextInput(
attrs={
"type": "email",
"id": "Email",
"name": "email",
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
}
),
)
first_name = forms.CharField(
max_length=50,
required=True,
widget=forms.TextInput(
attrs={
"type": "text",
"id": "FirstName",
"name": "first_name",
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
}
),
)
last_name = forms.CharField(
max_length=50,
required=True,
widget=forms.TextInput(
attrs={
"type": "text",
"id": "LastName",
"name": "last_name",
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
}
),
)
password1 = forms.CharField(
required=True,
widget=forms.PasswordInput(
attrs={
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
"type": "password",
"id": "Password1",
"placeholder": "Password",
}
),
)
password2 = forms.CharField(
required=True,
widget=forms.PasswordInput(
attrs={
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
"type": "password",
"id": "Password2",
"placeholder": "Password",
}
),
)
roll_number = forms.CharField(
max_length=50,
required=True,
widget=forms.TextInput(
attrs={
"type": "text",
"id": "RollNumber",
"name": "roll_number",
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
}
),
)
# department = forms.ChoiceField(
# choices=DEPARTMENT_CHOICES
# )
bio = forms.CharField(
widget=forms.Textarea(
attrs={
"rows": 8,
"cols": 50,
"class": "mt-1 w-full rounded-md border-gray-200 bg-white text-sm text-gray-700 shadow-sm",
}
)
)
class Meta:
model = Account
fields = "__all__"
class CustomLoginForm(AuthenticationForm):
username = forms.EmailField(
max_length=100,
required=True,
widget=forms.TextInput(
attrs={
"class": "block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md bg-gray-800 border-gray-600 placeholder-gray-400 focus:border-blue-400 focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300",
"placeholder": "Email Address",
"type": "email",
}
),
)
password = forms.CharField(
required=True,
widget=forms.TextInput(
attrs={
"class": "block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md bg-gray-800 border-gray-600 placeholder-gray-400 focus:border-blue-400 focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300",
"type": "password",
"placeholder": "Password",
}
),
)
login.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block title %}
Login
{% endblock title %}
{% block base %}
<div class="mx-auto max-w-screen-xl px-4 py-16 sm:px-6 lg:px-8">
<div class="mx-auto max-w-lg text-center">
<h1 class="text-2xl font-bold sm:text-3xl">Get started today!</h1>
<p class="mt-4 text-gray-500">
SIGN IN
</p>
</div>
<form action="" method="post" class="mx-auto mt-8 mb-0 max-w-md space-y-4">
{% csrf_token %}
<div>
<label for="email" class="sr-only">Email</label>
<div class="relative">
{{form.username}}
<span class="absolute inset-y-0 right-4 inline-flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"
/>
</svg>
</span>
</div>
</div>
<div>
<label for="password" class="sr-only">Password</label>
<div class="relative">
{{form.password}}
<span class="absolute inset-y-0 right-4 inline-flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
</span>
</div>
</div>
<div class="flex items-center justify-between">
<p class="text-sm text-gray-500">
No account?
<a class="underline" href="{% url 'register' %}">Sign up</a>
</p>
<button type="submit" class="ml-3 inline-block rounded-lg bg-teal-500 px-5 py-3 text-sm font-medium text-white hover:bg-teal-400 dark:hover:bg-teal-400">Sign In</button>
</div>
</form>
</div>
{% endblock base %}