I'm trying to use a class based view using django-tables2 to define the table and template returned based on what group the logged in user belongs to.
This is my attempt at doing so:
class cases(LoginRequiredMixin, SingleTableView):
login_url = '/account/login/'
if User.objects.filter(pk=self.request.user.id, groups__name='teachers').exists():
model = Graduation
table_class = TeachersTable
template_name = 'mysite/teachers.html'
elif User.objects.filter(pk=self.request.user.id, groups__name='students').exists():
model = Graduation
table_class = StudentsTable
template_name = 'mysite/students.html'
I think the approach is more or less correct (I've only learned about class based views today), but I am unsure how to access the user id.
The relevant parts of this view should only be called when a user is logged in (at least I think) because I'm using the LoginRequiredMixin, so 'self' should exist.
The answers I have seen addressing this problem say override get_queryset, but I am reluctant to do that as I think that will break django-tables2.
What is the best approach in this case to do what I am trying to do?
There are a few things going on here.
First, all code in a class runs when the module is loaded, not when the view is run. So your code is running at the wrong time. Partially because of this, you don't have access to self
.
self
isn't that magic, it doesn't appear from nowhere, you can only use it in class methods:
class Foo:
self.spam = "eggs" # Wrong, no self here.
class Bar:
def set_spam(self): # self is the instance of the class.
self.spam = "eggs" # Works.
I'm not sure what table_class is, from a search it looks like it comes from django-tables, so there's a bit of guesswork here. It seems like you want something like this:
class GraduationCaseView(LoginRequiredMixin, SingleTableView):
model = Graduation
def get_template_names(self):
if self.request.user.groups.filter(name='teachers').exists():
return ['mysite/teachers.html']
return 'mysite/students.html'
def get_table_class(self):
if self.request.user.groups.filter(name='teachers').exists():
return TeachersTable
return StudentsTable
This should work. There is an issue with this: you'd be doing the same database query twice. There are some ways around this, but it requires knowing a bit about CBVs and their execution order. Since I'm not sure what SingleTableView
is doing, this may or may not work:
class GraduationCaseView(LoginRequiredMixin, SingleTableView):
model = Graduation
def get_queryset(self):
qs = super().get_queryset()
if self.request.user.groups.filter(name='teachers').exists():
self.group = 'teachers'
else:
self.group = 'students'
return qs
def get_template_names(self):
if self.group == 'teachers':
return ['mysite/teachers.html']
return 'mysite/students.html'
def get_table_class(self):
if self.group == 'teachers':
return TeachersTable
return StudentsTable
You should probably read up on Python's documentation of classes, too, so you understand how they work.
One more thing, you don't need to set login_url
on your view if settings.LOGIN_URL
is set.