django - 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,他们就无法配置特定的查询函数来使用。
我的目标:
- 替换默认管理器
- 将基于用户的过滤器添加到 query_set
- 在所有应用程序配置中正常使用模型
想法(伪代码!)
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)
推荐阅读
- android - 在 Flutter 的 for 循环中使用时如何更改 OnTap 函数中的值
- javascript - 如何为Web浏览器的控制台日志编写for循环
- java - 使用 OpenCV 和 Nd4j 的 Android apk 太大
- c# - Itemsource 未更新 (wpf,c#)
- android - ConstraintLayout - 水平打包项目而不将宽度设置为 match_parent
- python - 如何在多个 conda 环境中安装同一个包?
- idfa - IDFA iOS14 返回被拒绝而不显示身份验证弹出窗口
- python-3.x - Python 3_Error "pywintypes.error: (5, 'OpenSCManager', 'Access is denied.')"
- c# - Json 对象不会在 C# 中反序列化
- autodesk-forge - Autodesk Forge Viewer v7:MarkupsCore 扩展