Django: управление доступом к страницам по соотношению "многие ко многим

У меня есть проблема блокировки доступа неавторизованного пользователя к определенным страницам. Список этих пользователей хранится в модели Many to Many в объекте Project. Ниже приведен models.py

class Project(models.Model): 
    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="projects_as_owner", null=True)
    project_managers = models.ManyToManyField(User, related_name="projects_as_pm", blank=True)
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    date_of_insert = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name


class Milestone(models.Model):
    project_fk = models.ForeignKey(Project, related_name="milestones", on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    date_of_insert = models.DateTimeField(auto_now_add=True)

def __str__(self):
        return self.name 

А views.py с классом у меня проблема

class NewMilestone(LoginRequiredMixin, generic.CreateView):
    model = Milestone
    fields = ['name', 'description']
    lookup_url_kwarg = 'p_id'
    template_name = 'main/new_milestone.html'

    # ... two functions, that work good, not important here ...

    def get_queryset(self):
        qs = super(NewMilestone, self).get_queryset()
        project = Project.objects.get(id=self.kwargs['p_id'])
        if(qs.filter(project_fk__owner=self.request.user).exists() or User.objects.filter(id=self.request.user.id).filter(projects_as_pm__id=project.id).exists()):
            return qs
        else:
            return Http404("You are not authenticated to this action")

Задача состоит в том, чтобы позволить аутентифицированным пользователям (владельцу и менеджеру проекта/ам) войти в это представление, а для всех остальных показать информацию о запрете доступа. Проблема в том, что это хорошо работало при проверке ТОЛЬКО владельца. Когда я добавил часть о менеджере проекта (после 'or'), программа позволяет любому пользователю получить доступ к этому представлению с помощью ссылки. Я перепробовал множество конфигураций для второго оператора 'if', и все, которые я использовал, имели этот недостаток.

Мой вопрос в том, как заставить его работать так, как я ожидаю от него?

PS. Английский не является моим родным языком, и я давно ничего не писал, поэтому прошу отнестись с пониманием.

Вы используете LoginRequiredMixin, что хорошо. Но тогда вы не установили ни один из доступных параметров.

LoginRequiredMixin наследуется от AccessMixin, и вы можете использовать все его параметры, с которыми не должно быть слишком сложно разобраться в вашем случае.

Вот возможная реализация:

class NewMilestone(LoginRequiredMixin, generic.CreateView):
    ... 
    # your class attributes 
    ...
    raise_exception = True

    # Returns a permission denied message. Default: empty string
    def get_permission_denied_message(self):
        return "Access is restricted to authenticated users" 

Если у вас raise_exception установлено значение True, то будет вызван метод get_permission_denied_message. В противном случае пользователь будет перенаправлен на login_url, который вы также должны будете объявить как атрибут класса.

Вернуться на верх