При попытке фильтрации по группе пользователей с использованием представления на основе классов с django-tables2 не удается получить доступ к self.user

Я пытаюсь использовать представление на основе классов с использованием django-tables2 для определения таблицы и шаблона, возвращаемого в зависимости от того, к какой группе принадлежит зарегистрированный пользователь.

Это моя попытка сделать это:

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'

Я думаю, что подход более или менее правильный (я только сегодня узнал о представлениях на основе классов), но я не уверен, как получить доступ к идентификатору пользователя.

Соответствующие части этого представления должны вызываться только тогда, когда пользователь вошел в систему (по крайней мере, я думаю), потому что я использую LoginRequiredMixin, поэтому должно существовать "я".

В ответах, которые я видел при решении этой проблемы, говорится, что переопределить get_queryset, но я не хочу этого делать, поскольку думаю, что это сломает django-tables2.

Как лучше всего в этом случае делать то, что я пытаюсь сделать?

1 ответ

Решение

Здесь происходит несколько вещей.

Во-первых, весь код в классе выполняется при загрузке модуля, а не при запуске представления. Значит, ваш код запущен не в то время. Частично из-за этого у вас нет доступа кself.

self это не волшебство, оно не появляется ниоткуда, вы можете использовать его только в методах класса:

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.

Я не уверен, что такое table_class, судя по поиску, похоже, что он исходит из django-tables, поэтому здесь есть немного догадок. Похоже, вы хотите что-то вроде этого:

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

Это должно работать. В этом есть проблема: вы выполняете один и тот же запрос к базе данных дважды. Есть несколько способов обойти это, но для этого нужно немного знать о CBV и порядке их выполнения. Поскольку я не уверен, чтоSingleTableView делает, это может работать, а может и не работать:

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

Вам, вероятно, также следует ознакомиться с документацией классов Python, чтобы понять, как они работают.

Еще одна вещь, вам не нужно устанавливать login_url на ваш взгляд, если settings.LOGIN_URL установлен.

Другие вопросы по тегам