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
, который вы также должны будете объявить как атрибут класса.