Giorgio Scarso
Giorgio Scarso

Reputation: 418

Middleware in django keeps redirecting, visiting admin-site not possible

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

Answers (1)

Dauros
Dauros

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

Related Questions