Django:自定义默认管理器,为所有视图/界面(自定义、管理、石墨烯、rest等)提供基于用户的查询



在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的一部分。

问题是:如何将其实现为一个通用的、与视图/接口无关的解决方案

安装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)

最新更新