【问题标题】:Restricting access in django at the model level在模型级别限制 django 中的访问
【发布时间】:2012-01-18 15:09:51
【问题描述】:

我有一个模型,我想根据用户的身份验证级别限制对对象的访问。匿名用户只能看到对象的子集,而授权用户可以访问所有对象。通读 django 书,我发现我可以在我的视图中使用 is_authenticated() 之类的检查,并根据该条件实现我的逻辑。但是我不希望这些检查散布在我的代码中,而是我希望能够为我的模型提供一些智能:模型应该只提供对当前用户权限可见的对象。

以下是我正在使用的几个模型:

class Collection(models.Model):
    VISIBILITY_CHOICES = (
    ('P', 'Private'),
    ('SP', 'Semi-Private'),
    ('PUB', 'Public')
    )

    name = models.CharField(max_length=40)
    visibility = models.CharField(max_length=3, choices=VISIBILITY_CHOICES)
    category = models.CharField(max_length=50)


class Image(models.Model):
    image = models.ImageField(upload_to= get_upload_to)
    collection = models.ForeignKey(Collection)

我做的一个查询示例是:collection_ids = Image.objects.values_list('collection',flat=True).distinct() -- 在这种情况下,我只想检查那些集合 id用户有权查看(即公共/私人/半私人)。

是否有可能或者我必须将授权逻辑放在我的视图中?

【问题讨论】:

    标签: django django-models django-views


    【解决方案1】:

    将身份验证放在模型上是这个逻辑的错误位置。视图正是这种逻辑存在的正确位置,这就是为什么 django 提供各种 auth 装饰器来保护视图,例如 login_required()

    模型的工作是提供对数据库的数据访问层。然后,您将创建任意数量的视图,以您想要的方式可视化数据。如果您需要匿名的数据视图,请创建一个视图来检查用户是否经过身份验证,并适当地格式化数据。

    【讨论】:

    • 如果我想实现 GraphQL 怎么办??
    • @WolfgangLeon,您想在模型级别添加身份验证逻辑是什么意思?
    • 在做了一些研究后,我发现石墨烯(Django 的 GraphQL)解析器返回 info.context.request。在 Query 类中检索查询集时,我们可以通过 request.user 进行过滤。 docs.graphene-python.org/projects/django/en/latest/…
    • 是的,但是您提供的确切链接描述了在视图/控制器级别而不是模型上执行身份验证逻辑。该模型只有一个外键来将帖子与用户相关联。该视图检查实际的用户身份验证,然后格式化适当的查询以过滤该用户的结果。模型应该始终只关注数据,而不是中间件或表示概念。
    【解决方案2】:

    请注意,在您提供的查询示例 (Image.objects.values_list('collection',flat=True).distinct()) 中,从未提及 request - 那么该查询如何能够检查当前用户?

    但这并不意味着您必须在视图中执行此操作 - 您可以向模型本身添加方法,甚至可以将 QuerySet 子类化以添加一个方法来检查当前请求,例如 .filter(foo=bar).allowed_for_user(user)

    看到这个答案:

    https://stackoverflow.com/a/4576649/16361

    确实链接到您的一篇古老的博客文章,虽然我似乎已经破坏了该答案中的链接,抱歉 - 正确的 URL 是:

    http://adam.gomaa.us/blog/2009/feb/16/subclassing-django-querysets/

    编辑:一篇较新的文章:

    http://zmsmith.com/2010/04/using-custom-django-querysets/

    另外,为了清楚起见 - 代码本身不必存在于您的视图中,但最终需要以一种或另一种方式涉及请求对象,因此您必须调用 从你的角度来看。

    【讨论】:

    • 我相信“控制器”部分来自模型视图控制器一词。这应该存在于视图中,或者存在于视图可以使用其上下文调用的一组单独的逻辑中。你真的不想用一堆特定于视图的逻辑来弄乱你的模型。
    • 不想逆势而上,但我不明白为什么。当然,从纯度的角度来看,混合东西是不好的。但是我将 Django 用于 Web 应用程序,我认为将其反映在我的模型中并不合适。例如,在模型定义中使用为对象生成 URL 的方法通常不会令人不悦。为什么我们不对“此请求可以访问我”方法使用相同的逻辑吗?
    • 感谢您的链接,我将研究子类化 QuerySet。
    • 我同意你可以做任何你想做的事。是的,我的回答确实源于纯度的角度。但我认为正是这些类型的指南使应用程序保持干净和易于理解。如果您需要确定您的数据在哪里被过滤以针对用户上下文,您总是可以假设它在视图中。视图也是包含请求上下文的地方。有对象级权限应用程序可以为用户生成对象权限,但它们也不进行任何类型的数据过滤。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多