Python 动态地将属性附加到ndb.Model的实例,并将它们放在to_dict()表示形式中

Python 动态地将属性附加到ndb.Model的实例,并将它们放在to_dict()表示形式中,python,architecture,google-cloud-datastore,app-engine-ndb,restful-architecture,Python,Architecture,Google Cloud Datastore,App Engine Ndb,Restful Architecture,我正在通过谷歌应用程序引擎NDB编写RESTAPI 我排除了现有库,因为我需要控制事务和缓存。 出于类似的原因,我排除了Google端点,也因为我不想使用它们提供的javascript客户端 在评估架构决策时,我遇到了一些问题和奇怪的情况,这是因为我对python和python风格的经验可能不够丰富 在这一刻,我试图提出一些指导原则来塑造我的代码库: 在处理程序->创建对象的字典表示形式 并将其作为json返回;执行身份验证和授权 检查 在服务中封装ndb交互 模型类始终接收模型对象或关键帧作

我正在通过谷歌应用程序引擎NDB编写RESTAPI

我排除了现有库,因为我需要控制事务和缓存。 出于类似的原因,我排除了Google端点,也因为我不想使用它们提供的javascript客户端

在评估架构决策时,我遇到了一些问题和奇怪的情况,这是因为我对python和python风格的经验可能不够丰富

在这一刻,我试图提出一些指导原则来塑造我的代码库:

  • 在处理程序->创建对象的字典表示形式
    并将其作为json返回;执行身份验证和授权
    检查
  • 在服务中封装ndb交互
  • 模型类始终接收模型对象或关键帧作为参数,并返回模型对象或模型列表
  • 模型类被导入并在服务中使用
我遇到的一件特别的事情是 我有一个多对多关系,我用一个映射模型实现了它,比如 UserOrganizationMembership,具有用户和组织的密钥

现在,在我的服务中,我希望返回一个对象,该对象包含当前用户所属组织的列表,并递归获取每个组织中的公司:

'organizations': [
  {
    'name': 'TEST'
    'companies': [ {company1}, {company2}]
  },
  {
    ...
  }
]
我这样做

  def user_organizatios_with_companies(user):
    def fetch_companies(x):
      x.companies = Company.by_organization(x) #NOTICE THIS
      return x

    user_organizations = [ membership.organization.get() for membership in UserOrganizationMembership.by_user(user)]
    return [fetch_companies(x) for x in user_organizations]
在突出显示的行中,我将动态属性“公司”附加到组织模型中

现在,如果我在处理程序中调用这个方法,当我创建字典表示以输出json时,ndb.Model.to_dict()实现会忽略动态附加的属性。

我尝试的一个解决方案是(在我的处理程序中)

但我不喜欢它,因为我需要知道每个组织都有一个“公司”属性,代码似乎有点复杂,不明显

另一种方法是重写ndb.Model.to_dict() 隔离动态附加的属性并提供字典表示,这简化了处理程序中的代码,使我只需对服务返回的内容调用_dict()

从google.appengine.ext导入ndb 导入util

class BaseModel(ndb.Model):
  created = ndb.DateTimeProperty(auto_now_add = True)
  updated = ndb.DateTimeProperty(auto_now = True)
  # App Engine clock times are always 
  # expressed in coordinated universal time (UTC).s

  def to_dict(self, include=None, exclude=None):
    result = super(BaseModel,self).to_dict(include=include, exclude=exclude)
    result['key'] = self.key.id() #get the key as a string
    # add properties dynamically added to the class
    dynamic_vars = {k:v for (k,v) in vars(self).iteritems() if not k.startswith('_')}
    for prop, val in dynamic_vars.iteritems():
      result[prop] = val.to_dict() if not isinstance(val, list) else [x.to_dict() for x in val]
    return util.model_db_to_object(result)

您对这种方法有什么建议吗?任何想法都将不胜感激

ndb通过网络支持动态属性

而不是将模型定义为:

class BaseModel(ndb.Model):
使用
Expando
定义它:

class BaseModel(ndb.Expando):
现在,如果您编写
x.companys=[…]
,则调用_to_dict()将输出这些公司。当您
put()
这些实体时要小心,因为任何动态添加的属性也会被放入数据存储中

class BaseModel(ndb.Expando):