【问题标题】:How to pass PK into a method decorator如何将PK传递给方法装饰器
【发布时间】:2020-05-11 16:44:56
【问题描述】:

大家好,我正在尝试对我的视图实施某种形式的访问控制。我的程序结构如下: 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)

这是我的网址:

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

任何帮助将不胜感激!

【问题讨论】:

    标签: python django django-models decorator access-control


    【解决方案1】:

    你不能。但是你可以改用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

    【讨论】:

      猜你喜欢
      • 2017-11-12
      • 2018-06-07
      • 2018-03-23
      • 1970-01-01
      • 2013-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多