Django-具有唯一数据的多个用户
我正在构建一个类似于财产维护应用程序的SaaS。一家物业维护公司会使用我的应用程序来管理多栋建筑和一大堆租户。因此,我们的建筑物和租户都由一家管理公司管理。但是,管理公司可能有多个员工(用户),他们都在管理这些建筑物/租户 由于这是一个SaaS,我希望有一大堆管理公司都使用我的应用程序来管理他们自己的一组建筑/租户。因此,每个管理公司只需要能够查看其数据,而无法访问另一个管理公司的数据 我不知道如何在Django实现这一点,尽管我有一个想法: 可能有一个名为Django-具有唯一数据的多个用户,django,Django,我正在构建一个类似于财产维护应用程序的SaaS。一家物业维护公司会使用我的应用程序来管理多栋建筑和一大堆租户。因此,我们的建筑物和租户都由一家管理公司管理。但是,管理公司可能有多个员工(用户),他们都在管理这些建筑物/租户 由于这是一个SaaS,我希望有一大堆管理公司都使用我的应用程序来管理他们自己的一组建筑/租户。因此,每个管理公司只需要能够查看其数据,而无法访问另一个管理公司的数据 我不知道如何在Django实现这一点,尽管我有一个想法: 可能有一个名为ManagementCompany的模
ManagementCompany
的模型,所有建筑物和租户都有一个指向该ManagementCompany
模型的ForeignKey
字段。该管理公司的员工将通过ForeignKey
连接到ManagementCompany
记录。这样,用户只能看到ManagementCompany
与用户匹配的建筑物/租户
这是一个合理的方法,还是有更好的方法 您当然可以使用
编辑:
鉴于您在对我的原始答案的评论中提到所使用的数据库是MySQL,django租户模式在您的案例中是无用的。如何使用多个数据库和数据库路由器,这样每个公司都可以有单独的数据库,使用数据库路由器,您可以通过它路由数据库请求
这可能是工作过度,但你可能会想出一个巧妙的方法来完成它。你想过子域吗 自定义子域是为SaaS产品的客户提供定制和区分内容的一种很好的方法,而无需求助于长URL路径
因此,当一家公司注册时,您可以调用_lower()方法的company name,也可以像Slack或Jira一样提示他们选择他们喜欢的方法。我建议您阅读这篇文章这取决于您希望在SaaS应用程序中存储数据的方式—所有实例使用单个数据库或多个数据库(每个实例都有单独的数据库)。当您想要添加新功能、迁移等时,多数据库方法是一种痛苦。单个数据库更易于管理,但您需要为每个型号添加一组
ForeignKey
对于单个db,您需要:
ForeignKey
,并手动对其进行过滤:
ForeignKey
和自定义保存方法的抽象模型,用于自动设置ForeignKey
get\u queryset
方法的自定义模型管理器,该方法将使用当前SaaS实例过滤所有ORM查询。此管理器应覆盖create
方法,以自动设置ForeignKey
,用于以下查询:Foo.objects.create(**data)
class SaaSModelAbstract(Model):
SAAS_FIELD_NAME = 'company'
company = ForeignKey(Company, null=True, blank=True)
class Meta:
abstract = True
def save(self, *args, **kwargs):
from .middleware import get_current_saas_instance
self.company = get_current_saas_instance()
super(SaaSModelAbstract, self).save(*args, **kwargs)
模型管理器示例:
class CurrentSaaSInstanceManager(models.Manager):
def get_current_saas_instance(self):
from .middleware import get_current_saas_instance
return get_current_saas_instance()
def get_queryset(self):
current_instance = self.get_current_saas_instance()
if current_instance is not None:
return super(CurrentSaaSInstanceManager, self).get_queryset().filter(
**{self.model.SAAS_FIELD_NAME: current_instance})
return super(CurrentSaaSInstanceManager, self).get_queryset()
def create(self, **kwargs):
current_instance = self.get_current_saas_instance()
if current_instance is not None:
kwargs[self.model.SAAS_FIELD_NAME] = current_instance
instance = self.model(**kwargs)
self._for_write = True
instance.save(force_insert=True, using=self.db)
return instance
示例模型:
class FooModel(SaaSModelAbstract):
# model fields, methods
objects = CurrentSaaSInstanceManager()
class BarModel(models.Model):
# model fields, methods
pass
示例查询:
FooModel.objects.all() # will return query with all objects for current SaaS instance
BarModel.objects.all() # will return all objects withoout SaaS filtering
# Create objects for SaaS instance:
FooModel.objects.create(**data)
# or:
foo = FooModel()
foo.save()
在这两种情况下(单个/多个db),django admin都能正常工作
我没有发布db router,因为实现非常简单,您所需要的一切都可以在django文档中找到。有趣的应用程序,但我使用的是MySQL。这个概念很有趣。@Garfonzo在了解您使用MySQL后编辑了我的答案。编辑后的答案可能适合您的要求。@Garfonzo与Multiple db和db router的用户属于一家公司(该公司基本上拥有自己的一个db实例)无法访问其他公司的数据感谢您的澄清-我认为多个数据库在任何更新和迁移中都会变得非常乏味。这是一篇有趣的文章,但它是否仍然提供了手动访问其他人数据的可能性?例如,如果用户有一个子域
user1.domain.com
,并且他们只是手动输入user2.domain.com
,那么生成的数据不就是user2
的数据吗?在他们的示例中,它将包括user2
的帐户?我的意思是,使用子域的想法很好,但我觉得需要内置更多的安全性,或者我遗漏了什么?嗯,这就是你需要实现身份验证和授权的地方。此外,我并不是要为每个用户创建子域,只是为公司创建子域,而且用户与公司之间有M2M关系(因为您可以同时在这两个领域工作)。假设一个用户已经在company1.domain.com中通过了身份验证,现在如果他创建了一个建筑对象,那么这个建筑将有两个字段,creator=user,company=company。现在,如果你想显示所有的company1建筑,你需要一个简单的查询集Building.objects.filter(company=company)是的,每个公司都有一个子域,其中有多个用户“连接”到一个公司。这似乎是一个非常有趣的方法。我可能走这条路
FooModel.objects.all() # will return query with all objects for current SaaS instance
BarModel.objects.all() # will return all objects withoout SaaS filtering
# Create objects for SaaS instance:
FooModel.objects.create(**data)
# or:
foo = FooModel()
foo.save()