限制用户获取或更新特定用户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