gpt4 book ai didi

python - 如何将 Model.objects.all() 限制为属于一个组织的数据

转载 作者:太空宇宙 更新时间:2023-11-04 04:53:31 25 4
gpt4 key购买 nike

我正在开发一个 Web 应用程序,它将存储多个 Organizations,其中每个组织都有自己的用户。组织由 (CharField) 标识,用户只能看到属于他们自己组织的数据。出于简单性和性能原因,我将所有组织的数据存储到同一个数据库中,而不是创建 N 个数据库/ View 。

我想要实现的是一种简单的方法,可以在用户请求的上下文中限制相关的查询。

我尝试了什么

过滤所有查询集

由于每个用户都属于一个组织,因此想到的第一个选择是使用这样定义的queryset:

queryset = MyModel.objects.all(domain=request.user.domain)

我无法使用此解决方案,因为它会强制开发人员手动过滤整个 Web 应用程序中的所有查询。如果有人忘记正确过滤查询集,一个组织的用户可以看到其他组织的数据。它很容易出错。

线程本地化

因为我可以在请求中找到用户。另一种解决方案是通过中间件公开请求,并使用将执行请求的用户域自动按域过滤。为此,我找到了这个 question但意见分歧较大。

我仍然需要弄清楚为什么使用线程局部变量是一个糟糕的选择。我在 Freenode/#django 上讨论了这个,但没有人详细说明避免它的原因。我想更好地了解此解决方案的优缺点。

模型混合

我想要一个设置两个管理器的 mixin(比方说 DomainModelMixin):

objects = DomainManager()
super_objects = models.Manager()

super_objects 是默认管理器(未过滤),objects 是自定义管理器,按域过滤并仅提供与组织有关的数据。

问题是在模型层我们没有请求,因此我们没有用户,我们也不知道将查询集限制到哪个。我们如何将 domain 传递给管理器?

大问题

我们如何以对开发人员透明且易于使用的方式自动过滤 objects.all()?如果我们想在没有 Request 对象的上下文(例如交互式 shell 或测试)中使用相同的逻辑怎么办?

最佳答案

编辑:最后我要离开原来的帖子,解释为什么这不是一个好主意。

管理器是可能的,您可以向其添加自定义函数,并使用它来添加用户参数。

此技术记录在 Django Docs, adding extra manager methods 上.文档示例通过编写完整的自定义 SQL 有点误导。您可以使用普通的 ORM 编写一些东西。你需要做什么:- 自定义管理器,使用 get_for_user(self, user) 左右的方法返回过滤后的查询集
- 在模型中,将 objects 重定向到新的管理器 objects = CustomManager()
- 将它与 model.objects.for_user(user)

一起使用

以下为原帖,请无视。它最终太老套了,无法考虑。它使用不太相关的方法使模型膨胀。在 objects 中使用自定义管理器还有一个好处,即不会偏离标准的做事方式,希望 IDE 建议能够帮助使用正确的方法。

我也希望用 Django 管理器来解决这个问题,这将是解决这个问题的最惯用的方法,但是模型层缺少请求信息使其不合适。

相反,我认为减少错误的最好方法就是在模型中简单地自定义一个函数,并在它可以是动态的地方调用它。我假设您的用户正在扩展 Django 用户。

//models.py
class MyUserModel(model.Models):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="my_user_model")
domain = models.ForeignKey(Domain, on_delete=models.CASCADE)

def domains(self):
queryset = MyModel.objects.filter(domain=self.domain)
return queryset

// View or else
my_user = request.user.my_user_model
domains_queryset = my_user.domains()

您还可以在那里使用一些鸭子类型,如果您有多种类型的自定义用户,只需为每个用户实现相关的 domains() 函数,它就会为您提供适当过滤的查询集。不要忘记查询集是惰性的,因此您可以从 View 中添加更多过滤器。

关于python - 如何将 Model.objects.all() 限制为属于一个组织的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47641181/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com