3

我正在使用命名空间设计一个多租户系统。

用户通过 OpenID 进行身份验证,用户模型保存在 Cloud Datastore 中。用户将被分组到组织中,也在数据库中建模。应用程序数据需要按组织进行分区。

所以想法是将命名空间映射到“组织”。

当用户登录时,会在会话中查找并保存他们的组织。

WSGI 中间件检查会话并相应地设置命名空间。

我的问题涉及如何最好地管理“全局”数据(即用户和组织)和应用程序数据(按组织命名空间)之间的切换

我目前的方法是使用 python 装饰器和上下文管理器来临时切换到全局命名空间,以进行访问此类全局数据的操作。例如

standard_datastore_op()

with global_namespace():
    org = Organization.query(Organization.key=org_key)

another_standard_datastore_op(org.name)

或者

@global_namespace
def process_login(user_id):
    user = User.get_by_id(user_id)

这也意味着模型具有跨命名空间的 KeyProperties:

class DomainData(ndb.Model): # in the current user's namespace

    title = ndb.StringProperty()
    foreign_org = ndb.KeyProperty(Organization) #in the "global" namespace

这似乎是一种合理的方法吗?我觉得这有点脆弱,但我怀疑这是因为我不熟悉在 App Engine 中使用命名空间。我的替代想法是将 Cloud Datastore 中的所有“全局”数据提取到外部 Web 服务中,但如果可能的话,我宁愿避免这种情况。

非常感谢您的建议。提前致谢

4

1 回答 1

0

装饰器是一种非常好的方法,它还具有清楚地标记哪些功能在组织特定的命名空间范围之外运行的好处。

def global_namespace(global_namespace_function):
  def wrapper():
    # Save the current namespace.
    previous_namespace = namespace_manager.get_namespace()

    try:
        # Empty string = default namespace, change to whatever you want to use as 'global'
        global_namespace = ''
        # Switch to 'global' namespace
        namespace_manager.set_namespace(global_namespace)

        # Run code that requires global namespace
        global_namespace_function()
    finally:
        # Restore the saved namespace.
        namespace_manager.set_namespace(previous_namespace)

  return wrapper

在相关的说明中,我们还有关于使用命名空间进行多租户的文档。

于 2016-12-29T15:57:15.767 回答