首页 > 解决方案 > Django:自定义默认管理器,针对所有视图/界面(自定义、管理、石墨烯、休息等)提供基于用户的查询

问题描述

在 Django 中,我试图实现某种“安全中间件”,如果登录的用户匹配,它只允许访问某些数据库信息。

到目前为止,我发现了两种方法:中间件或管理器中的自定义函数(两者都在这里解释Django 自定义管理器 - 如何只返回登录用户创建的对象?)。

最干净的解决方案示例:自定义函数

class UserContactManager(models.Manager):
    def for_user(self, user):
        return self.get_query_set().filter(creator=user)

class MyUser(models.Model):
    # Managers
    objects = UserContactManager()

# then use it like this in views
data = MyUser.objects.for_user(request.user)

但是,此解决方案仅适用于您可以控制调用此自定义函数的代码(此处:)for_user()。但是,如果您使用第三方应用程序,如 Django-REST、Graphene 或 AdminViews,他们就无法配置特定的查询函数来使用。

我的目标:

  1. 替换默认管理器
  2. 将基于用户的过滤器添加到 query_set
  3. 在所有应用程序配置中正常使用模型

想法(伪代码!)

from django.x import current_user

class UserBasedManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(author=current_user.name)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)

    objects = UserBasedManager() # The default manager.

现在我可以Book在所有扩展中正常使用该模型。

我知道这个解决方案会有一些缺点,这对我来说没问题:

我的用例

我有一个项目,它可以通过不同的界面(管理页面、自定义视图、rest、graphql)访问数据。由于我有这么多接口,我不想在视图中实现访问权限。这将花费太多时间并且难以维护,并且在一个特定视图/界面中出现安全问题的风险太高。

假设我将 git 存储库的提交存储在数据库中。并且用户应该可以访问所有提交,这些提交是用户具有 READ 访问权限的 repos 的一部分。

问题是:如何将其实现为通用的、独立于视图/界面的解决方案?

标签: djangodjango-modelsdjango-managers

解决方案


安装django-threadlocals包并调用get_current_user函数获取当前用户

from threadlocals.threadlocals import get_current_user

class UserBasedManager(models.Manager):
    def get_queryset(self):
        current_user = get_current_user()
        return super().get_queryset().filter(author=current_user.name)

推荐阅读