如何将 PK 传递给方法装饰器
How to pass PK into a method decorator
大家好,我正在尝试对我的视图实施某种形式的访问控制。我的程序结构如下:
1 个项目有一些用户以外键的形式绑定到它。我只希望让参与其中的人看到这个项目。然而,问题是我用来查询模板数据库的 PK 在我的 URL 中,无权访问项目的用户可以简单地更改 url 查询并获得对项目的访问权限他们无权访问。
我遇到了 django 的 user_passes_test 方法装饰器,并认为这正是我实现此用户访问控制所需要的。
这是我想出的一些代码:
我的看法:
@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)
然而,我似乎无法简单地从 url 传递 PK,因为当 运行 服务器时我收到此错误:
@method_decorator(user_passes_test(project_check(id) , name='dispatch'))
TypeError: project_check() missing 1 required positional argument: 'id
任何帮助将不胜感激!
你不能。但是您可以只使用 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
.
大家好,我正在尝试对我的视图实施某种形式的访问控制。我的程序结构如下: 1 个项目有一些用户以外键的形式绑定到它。我只希望让参与其中的人看到这个项目。然而,问题是我用来查询模板数据库的 PK 在我的 URL 中,无权访问项目的用户可以简单地更改 url 查询并获得对项目的访问权限他们无权访问。
我遇到了 django 的 user_passes_test 方法装饰器,并认为这正是我实现此用户访问控制所需要的。
这是我想出的一些代码:
我的看法:
@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)
然而,我似乎无法简单地从 url 传递 PK,因为当 运行 服务器时我收到此错误:
@method_decorator(user_passes_test(project_check(id) , name='dispatch'))
TypeError: project_check() missing 1 required positional argument: 'id
任何帮助将不胜感激!
你不能。但是您可以只使用 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
.