'My user roles returns either list index out of range or takes me back to log in even though the right role is logged in
I have created user roles within my Django application and have designated users their roles within the admin interface but when I log in an try to access the restricted access page using the correct role I am either returned to the log in page or met with a list index out of range error and I am very confused to as why this is.
Models.py
from pickle import TRUE
from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from django.urls import reverse
from django.utils import timezone
ROLES = (
('0','Researcher'),
('1','Clinician'),
('2','Superuser'),
)
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User, on_delete=models.CASCADE)
# The additional attributes we wish to include.
picture = models.ImageField(upload_to='profile_images', default='default/default.jpg', blank=True)
role = models.CharField(max_length=1000, choices=ROLES, default='0')
is_active = models.IntegerField(default = 1,
blank = True,
null = True,
help_text ='1->Active, 0->Inactive',
choices =(
(1, 'Active'), (0, 'Inactive')
))
created_on = models.DateTimeField(default = timezone.now)
updated_on = models.DateTimeField(default = timezone.now,
null = True,
blank = True
)
Views.py
from django.shortcuts import render, redirect
from django.urls import reverse
from django.http import HttpResponse
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from parasites_app.models import Contact, UserProfile,Category,Photo
from parasites_app.forms import ContactForm
from django.core.mail import send_mail
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test
#for the permissions decorators
def find_role(u):
userprofile = UserProfile.objects.filter(user = u)[0]
return userprofile.role
#create decorators to dictate permissions
#@clinician_required
def clinician_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url='login'):
actual_decorator = user_passes_test(
lambda u: u.is_active and find_role(u) == 'Clinician',
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
@clinician_required
def Clinician(request):
category = request.GET.get('category')
if category == None:
photos = Photo.objects.all()
else:
photos = Photo.objects.filter(
category__name=category)
categories = Category.objects.all()
context = {'categories': categories, 'photos': photos}
return render(request,'parasites_app/Clinician.html',context)
Solution 1:[1]
I think the issue might be with find_role(u) == 'Clinician'
The role returned from find_role is the numeric key stored for that tuple of choices. Perhaps find_role can be rewritten as below:
def find_role(u):
userprofile = UserProfile.objects.filter(user = u)[0]
return userprofile.get_role_display()
I might also suggest that you move the logic of what determines the user to be a clinitian onto the user model. e.g. create a is_clinician method that returns true or false and use that in the check for permission perhaps. Just a suggestion.
I also noticed that the max_length for the role field is 1000, this might take up more space in the DB than you need and you'll feel the pain later when you have thousands of entries and need to shrink the DB, since the role is just one char you can set the max_length to 1 and you should be fine, or even 10 in case you want to expand it at some point, but 1000 off the bat might just cause the DB to be unnecessarily large.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dharman |
