Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
限制用户获取或更新特定用户django创建的对象_Django_Django Rest Framework - Fatal编程技术网

限制用户获取或更新特定用户django创建的对象

限制用户获取或更新特定用户django创建的对象,django,django-rest-framework,Django,Django Rest Framework,我有一个任务模型,比如 class Tasks(models.Model): made_by=models.ForeignKey(User , on_delete=models.CASCADE) title = models.CharField(max_length=100,null=True,blank=True) 我有一个像这样的观点 def get(self, request, id): task = Tasks.objects.get(id=id

我有一个任务模型,比如

class Tasks(models.Model):
    made_by=models.ForeignKey(User , on_delete=models.CASCADE)
    title = models.CharField(max_length=100,null=True,blank=True)
我有一个像这样的观点

    def get(self, request, id):
        task = Tasks.objects.get(id=id)
        if task:
            serializer = TasksSerializer(task, many=False)
            return Response(success_response(serializer.data, "Contact Information."
 status=status.HTTP_200_OK)

和一个
以同样的方式放置
。我只想检查由它创建的用户是否可以访问它
。有什么聪明的方法可以做到这一点吗?我不想在所有视图和以后的视图中再次查询check。

有几种不同的方法可以实现这一点,但我认为最简单的方法是测试用户的made by状态。i、 e

    def run_task(self, request, id):
         if request.user.made_by == 'Foo Bar'
            . . . .
            return Response(success_response ...
         else
            return Response(failure_response ...
另一种更复杂的方法是使用标准帐户模型perms,并将“任务”perms设置为false。i、 e

def has_task_perms(self):
    return False
然后在用户创建过程中,通过任何一种用户类型都可以给任务perms。我所知道的最常见的方法是使用客户经理(一个完整的兔子本身),即


既然您使用的是基于类的视图,我建议您重写类的
dispatch
方法。每当有人调用视图时,不管是什么方法,都会执行这个类

在这个分派方法中,您首先可以像在当前代码的get函数中一样检索任务对象。在该步骤之后,您可以执行一项检查,以查看
请求.user
是否等于对象的
生成

例如:

def dispatch(self, request, id):
    self.task = Tasks.objects.get(id=id)  # consider using get_object_or_404

    # Check if user is owner of task, otherwise throw a 404
    if request.user != self.task.made_by:
        raise Http404()

    # Will continue execution as normal, calling get() if a get-request was made
    # the variable self.task will be available in this function, so re-retrieving the
    # object is not necessary
    return super().dispatch(request, id)

此外,我还建议使用默认的
LoginRequiredMixin
,以确保只有登录的用户才能访问该视图。在许多情况下,它可以消除定制的书面检查

当处理与特定实例无关的更一般的权限时,
PermissionRequiredMixin
也是一个不错的选择


对于更具体的-自定义-权限,您还可以使用
userpassestimixin
在专用测试函数中写入检查,以保持代码更干净。

我尝试了很多解决方案,但最后我制作了一个这样的装饰器

def task_ownership_check(func):
    def wrapper(request,*args, **kwargs):
        print(kwargs['id'])
        try:
           task = Tasks.objects.get(id=kwargs['id'])
        except Tasks.DoesNotExist:
            return Response(failure_response(data={}, msg='No task matching query found'),
                            status=status.HTTP_404_NOT_FOUND)

        if args[0].user != task.todolist.for_user:
            return Response(failure_response(data={'error': 'You are not allowed to access this record'},
                                             msg='You are not allowed to access this record'),
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            return func(args[0], kwargs['id'])

    return wrapper

因此,现在我可以通过在任何任务上包含@task\u ownership\u check来轻松检查

您在视图中是否使用了身份验证类?如果是这样,您可以通过从
request.User.Tasks.get
反向引用
Tasks
来访问与
User
类相关的
任务。还可以将
made\u by=models.ForeignKey(User,on\u delete=models.CASCADE)
更改为
made\u by=models.ForeignKey(User,related\u name=“Tasks”,on\u delete=models.CASCADE)
@Rfroes87是的,我正在使用身份验证,但不想在任何地方都签入,因为它不会是干代码。我想为此做一些类似于Decorator的事情,你能添加完整的视图类和序列化器类吗?看起来很有趣,请检查一下。所以,如果不需要添加装饰器?@gamer我不认为在这种情况下使用装饰器是最好的解决方案,尽管如果你真的想这样做的话,也可能是这样。尽管它并不总是可行或是最好的选择,但我建议尽量使用Django的核心特性。例如,你也可以在函数中添加一个
login\u required
decorator(这也是一个内置的Django功能),但我个人建议不要这样做,因为已经有一个内置的mixin可以为你完成整个过程。我不能返回像custom msg这样的东西,而不是Http404@gamer你当然可以!只需使用重定向或任何其他http响应(例如呈现另一个模板)替换
raise Http404()
部分即可。出现了一些可疑的情况。我无法使用jwt访问调度功能中的用户,它的另一个用户和输入方法工作正常
def task_ownership_check(func):
    def wrapper(request,*args, **kwargs):
        print(kwargs['id'])
        try:
           task = Tasks.objects.get(id=kwargs['id'])
        except Tasks.DoesNotExist:
            return Response(failure_response(data={}, msg='No task matching query found'),
                            status=status.HTTP_404_NOT_FOUND)

        if args[0].user != task.todolist.for_user:
            return Response(failure_response(data={'error': 'You are not allowed to access this record'},
                                             msg='You are not allowed to access this record'),
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            return func(args[0], kwargs['id'])

    return wrapper