Django中的对象所有权

时间:2009-06-16 00:09:49

标签: django

我想知道如何使用django模型完成一个简单的“对象所有权”系统,默认情况下,只有对象的所有者才能编辑它。

我正在尝试允许“管理”组代表对象所有者编辑所有对象,并在此时添加了自定义权限:

class Meta:
    permissions     = (
        ("manage_object", "Can manage objects"),
    )

为了建立'所有权',我已经玩弄了为模型添加def的想法:

def owner(self):
    return self.user

但是,我怎么可能走得更远?我可以在视图中实现权限,并使用模板显示相关的UI,即:

if request.user is object.owner:
    # ... do stuff
elseif request.user.has_perm.can_manage:  # this line is probably not right
    # ... do something else

...然后在模板级别上呈现不同的UI元素。

所以,问题是:

  • 这种方法有哪些缺点/好处?
  • 有推荐吗?
  • 或其他任何以前实施的方法?

非常感谢!

3 个答案:

答案 0 :(得分:17)

我的方法是为模型添加一个方法:

class YourModelWithOwnership(models.model):
    ...

    def user_can_manage_me(self, user):
        return user == self.user or user.has_perm('your_app.manage_object')

每当需要权限检查时,我都会调用该方法,并根据结果采取一些措施。所以对于一个将是

的视图
from django.shortcuts import get_object_or_404
...

def view_func(request, item_id):
    item = get_object_or_404(YourModelWithOwnership, id=item_id) # or whatever is needed to get the object
    if not item.user_can_manage_me(request.user):
        # user not allowed to manage
        ...
    else:
        ...

后来我可能会意识到,在每个需要该测试的视图中,仍然需要编写一些样板代码,因此我会实现一个在用户无法管理对象时抛出的异常...

class CannotManage(Exception):
    pass

...并为模型添加另一种方法:

from django.db import models
from django.shortcuts import get_object_or_404

class YourModelWithOwnership(models.model):
    ...

    @classmethod
    def get_manageable_object_or_404(cls, user, *args, **kwds):
        item = get_object_or_404(cls, *args, **kwds)
        if not item.user_can_manage_me(user):
            raise CannotManage
        return item

然后,在视图函数中,可以使用它:

def view_func(request, item_id):
    item = YourModelWithOwnership.get_manageable_object_or_404(request.user, id=item_id)
    ...

当用户不是所有者且没有适当的权限时,这当然会引发异常。该异常可以在custom middleware类的process_exception()方法中处理,因此对于不允许用户弄乱该对象的所有实例,都有一个处理程序。

答案 1 :(得分:2)

前段时间我写了the usual technique for doing this in the admin。您可能希望通读它以了解实现的工作原理。

答案 2 :(得分:0)

您可以查看RowLevelPermissions分支。它甚至还没有被包括在1.1 beta中,我想它仍然需要一些开发。