Как передать PK в метод декоратор - PullRequest
1 голос
/ 25 января 2020

Здравствуйте, ребята, я пытаюсь реализовать некоторую форму контроля доступа в моих представлениях. Моя программа структурирована так: 1 проект имеет несколько пользователей, которые привязаны к нему в виде внешнего ключа. Я только позволю sh разрешить тем, кто участвует в нем, просматривать этот проект. Проблема, однако, заключается в том, что PK, который я использую для запроса базы данных для моего шаблона, находится в моем URL-адресе, пользователи, которые не имеют доступа к проекту, могут просто изменить URL-запрос и получить доступ к элементам, к которым у них нет доступа.

Я наткнулся на декоратор метода user_passes_test django и подумал, что это именно то, что мне нужно для реализации этого контроля доступа пользователя.

Вот код, который я придумал:

Мой взгляд:

@method_decorator(user_passes_test(project_check(id)),name ='dispatch')
class ProjectDetailView(CreateView):

##this is actually not relavant##
  model = SalesNotation
  fields = ['sales_notes']
  exclude = ['notation_id']
  template_name = 'rnd/projects.html'
  context_object_name = 'form'
##this is actually not relavant##

  def get_context_data(self, **kwargs):
    id = self.kwargs['id']
    context = super(ProjectDetailView, self).get_context_data(**kwargs)
    context['projects'] = SalesProject.objects.filter(sales_project_id = id)

Это мой URL:

 path('projects/<int:id>/', ProjectDetailView.as_view(), name = 'rnd-projects'),

Это моя модель проекта:

    class SalesProject(models.Model):
sales_project_id = models.AutoField(primary_key=True)
sales_project_name = models.CharField(max_length=100)
salesExtra = models.ManyToManyField('SalesExtra', blank=True)

Вот моя расширенная пользовательская модель, которую я использую для хранения другой информации:

class SalesExtra(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
user_type = models.TextField(max_length=500, choices= role)
contact = models.IntegerField()
email = models.TextField(max_length=30,default = 'your email here')

Вот декоратор метода, который я использую:

def project_check(user,id):
return SalesProject.objects.filter(sales_project_id=id).filter(salesExtra__user=user)

Однако кажется, что я не могу просто передать PK с URL-адреса, когда получаю эту ошибку при запуске сервера:

    @method_decorator(user_passes_test(project_check(id) , name='dispatch'))
TypeError: project_check() missing 1 required positional argument: 'id

Любая помощь будет принята с благодарностью!

1 Ответ

1 голос
/ 25 января 2020

Вы не можете. Но вы можете просто использовать UserPassesTestMixin вместо:

from django.contrib.auth.mixins import UserPassesTestMixin

class ProjectDetailView(UserPassesTestMixin, CreateView):

##this is actually not relavant##
  model = SalesNotation
  fields = ['sales_notes']
  exclude = ['notation_id']
  template_name = 'rnd/projects.html'
  context_object_name = 'form'
##this is actually not relavant##

  def get_context_data(self, **kwargs):
    id = self.kwargs['id']
    context = super(ProjectDetailView, self).get_context_data(**kwargs)
    context['projects'] = SalesProject.objects.filter(sales_project_id = id)

  def test_func(self):
    return SalesProject.objects.filter(sales_project_id=self.kwargs["id"]).filter(salesExtra__user=self.request.user)

Примечание test_func здесь, который выполняет проверку. self.kwargs["id"] даст вам id.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...