【发布时间】:2014-12-22 23:44:25
【问题描述】:
我试图了解命名空间和祖先在 GAE 中的工作方式。 所以我制作了一个简单的多租户“ToDo List”应用程序,其中每个租户都是一个用户。所以我在 appengine_config.py 中设置命名空间,如下所示:
def namespace_manager_default_namespace_for_request():
name = users.GetCurrentUser().user_id()
return name
然后在我的 main.py 中管理视图,如下所示:
#Make tasks with strong consistency by giving them a parent
DEFAULT_TASKS_ANCESTOR = ndb.Key('Agenda', 'default_agenda')
class TasksList(webapp2.RequestHandler):
def get(self):
namespace = namespace_manager.get_namespace()
tasks_query = Task.query(ancestor=DEFAULT_TASKS_ANCESTOR)
tasks = tasks_query.fetch(10, use_cache=False)
context = {
'tasks': tasks,
'namespace': namespace,
}
template = JINJA_ENVIRONMENT.get_template('templates/tasks_list.html')
self.response.write(template.render(context))
def post(self):
name = cgi.escape(self.request.get('name'))
task = Task(parent=DEFAULT_TASKS_ANCESTOR)
task.name = name
task.put()
self.redirect('/tasks_list')
...这给出了泄漏的数据:
我以 userA 的身份登录,创建了一个任务,然后注销并以另一个用户 (userB) 的身份再次登录,我可以从 userA 看到该任务。 我从管理面板确认任务实体来自不同的命名空间,并且祖先也不同,“因为它包含命名空间?”。
我还使用
.fetch(10, use_cache=False)关闭了缓存。但问题仍然存在。所以这不是缓存问题。所以最后我在
.query()和.put()之前创建了父级,它确实有效!像这样:DEFAULT_TASKS_ANCESTOR = ndb.Key('Agenda', 'default_agenda') tasks_query = Task.query(ancestor=DEFAULT_TASKS_ANCESTOR)
但现在我有问题......
为什么有效?由于这些任务实体不共享相同的命名空间,我如何从另一个命名空间查询数据?即使我错误地从另一个命名空间查询祖先,我应该获取数据吗?
来自 namespaceA 的 DEFAULT_TASKS_ANCESTOR 是否与来自 namespaceB 的 DEFAULT_TASKS_ANCESTOR 相同,或者它们是两个完全不同的祖先?
命名空间是否真的对数据存储区中的数据进行了划分,或者事实并非如此?
如果祖先即使在命名空间中也扮演着如此重要的角色,我是否仍应使用命名空间或祖先来划分多租户应用程序中的数据?
提前谢谢你!
【问题讨论】:
标签: python google-app-engine namespaces multi-tenant