Reputation: 418
I am writing a django project where I need to separate the pages and the accounts. Do to so, I wrote a LoginCheckMiddleWare. The problem is that I am not able to visit the django-admin site anymore, because it keeps redirecting me. I don't what I did wrong. I also have an EmailBackEnd.py file, that I use for logging in with the email and not the username.
LoginCheckMiddleWare.py
from django.http.response import HttpResponseRedirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
class LoginCheckMiddleWare(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
modulename = view_func.__module__
user = request.user
if user.is_authenticated:
if user.user_type == '1':
if modulename == 'user.views' or modulename == 'django.views.static':
pass
elif modulename == 'user.log_views':
pass
else:
return HttpResponseRedirect(reverse('user:admin_index'))
elif user.user_type == '2':
if modulename == 'instructor.views' or modulename == 'django.views.static':
pass
elif modulename == 'user.log_views':
pass
else:
return HttpResponseRedirect(reverse('instructor:instructor_index'))
elif user.user_type == '3':
if modulename == 'student.views' or modulename == 'django.views.static':
pass
elif modulename == 'user.log_views':
pass
else:
return HttpResponseRedirect(reverse('student:student_index'))
else:
return HttpResponseRedirect(reverse('user:login_user'))
else:
if request.path == reverse('user:login_user') or modulename == 'django.contrib.auth.views':
pass
else:
return HttpResponseRedirect(reverse('user:login_user'))
EmailBackEnd.py
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
class EmailBackEnd(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=username)
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None
log_views.py
from django.urls import reverse
from django.shortcuts import render
from django.http import HttpResponseRedirect
from user.EmailBackEnd import EmailBackEnd
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
def login_user(request):
if request.method == 'POST':
user = EmailBackEnd.authenticate(request, username=request.POST.get(
"email"), password=request.POST.get("password"))
if user != None:
login(request, user)
if user.user_type == '1':
return HttpResponseRedirect(reverse('user:admin_index'))
elif user.user_type == '2':
return HttpResponseRedirect(reverse('instructor:instructor_index'))
else:
return HttpResponseRedirect(reverse('student:student_index'))
else:
messages.error(request, 'Invalid Login Details')
return HttpResponseRedirect(reverse('user:login_user'))
return render(request, 'user/login.html')
settings.py
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',
'user.LoginCheckMiddleWare.LoginCheckMiddleWare',
]
AUTHENTICATION_BACKENDS = ['user.EmailBackEnd.EmailBackEnd']
urls.py
urlpatterns = [
path('', include('user.urls')),
path('admin/', admin.site.urls),
path('student/', include('student.urls')),
path('instructor/', include('instructor.urls')),
]
models.py
class CustomUser(AbstractUser):
user_type_data = (
(1, 'Admin'),
(2, 'Instructor'),
(3, 'Student')
)
user_type = models.CharField(
max_length=20, choices=user_type_data, default=1)
Any suggestion? Thank you very much in advance
Upvotes: 0
Views: 556
Reputation: 10557
The user_type
attribute is an integer, but you are making string comparisons in the view logic, so the else
branch has been selected everywhere because 1 != '1'
in Python. Have a look at Django's IntegerChoices model class, which is created exactly for your use case.
We can define an UserType
model:
class UserType(models.IntegerChoices):
ADMIN = 1
INSTRUCTOR = 2
STUDENT = 3
And use it in the choices
parameter of user_type
:
class CustomUser(AbstractUser):
user_type = models.CharField(
max_length=20, choices=UserType.choices, default=UserType.ADMIN)
And also import it in the view functions and use it for the comparisons:
class LoginCheckMiddleWare(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
modulename = view_func.__module__
user = request.user
if user.is_authenticated:
if user.user_type == UserType.ADMIN:
if modulename == 'user.views' or modulename == 'django.views.static':
pass
elif modulename == 'user.log_views':
pass
else:
return HttpResponseRedirect(reverse('user:admin_index'))
...
It also makes your code more readable, since using UserType.ADMIN
tells the reader what you want to do.
Upvotes: 1