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

Dynamically attach properties to an instance of ndb.Model and have them in the to_dict() representation

我正在通过 Google App Engine NDB 编写一个 REST api

我排除了现有库,因为我需要控制事务和缓存。

出于类似的原因,我排除了 Google Endpoints,也因为我不想使用他们提供的 javascript 客户端。

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

在这一刻,我试图提出一些应该塑造我的代码库的指导方针:

  • 在 Handlers -> 创建对象的字典表示

    并将它们作为 json 返回;执行身份验证和授权

    支票

  • 将ndb交互封装在Services中
  • 模型类总是接收模型对象或键作为参数并返回模型对象或模型列表
  • 模型类被导入并在服务中使用

我遇到的一件特别的事情是

我使用映射模型实现了多对多关系,例如

UserOrganizationMembership,具有 User 和 Organization

的密钥

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

'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]
xs = Service.user_organizatios_with_companies(u)

organizations = [x.to_dict() for x in xs]

for x in xrange(0,len(xs)):

 organizations[x]['companies'] = xs[x].to_dict()

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)

class BaseModel(ndb.Model):
class BaseModel(ndb.Expando):

我这样做

'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]
xs = Service.user_organizatios_with_companies(u)

organizations = [x.to_dict() for x in xs]

for x in xrange(0,len(xs)):

 organizations[x]['companies'] = xs[x].to_dict()

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)

class BaseModel(ndb.Model):
class BaseModel(ndb.Expando):

在突出显示的行中,我将动态属性 \\'companies\\' 附加到组织模型

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

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

'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]
xs = Service.user_organizatios_with_companies(u)

organizations = [x.to_dict() for x in xs]

for x in xrange(0,len(xs)):

 organizations[x]['companies'] = xs[x].to_dict()

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)

class BaseModel(ndb.Model):
class BaseModel(ndb.Expando):

但我不喜欢它,因为我需要知道每个组织都有一个\\'companies\\'属性,而且代码看起来有点复杂而且不明显

另一种方法是覆盖 ndb.Model.to_dict()

隔离动态附加属性并提供字典表示,这简化了我在处理程序中的代码,让我只对服务返回的内容调用 to_dict()。

从 google.appengine.ext 导入 ndb

导入实用程序

'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]
xs = Service.user_organizatios_with_companies(u)

organizations = [x.to_dict() for x in xs]

for x in xrange(0,len(xs)):

 organizations[x]['companies'] = xs[x].to_dict()

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)

class BaseModel(ndb.Model):
class BaseModel(ndb.Expando):

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


ndb 通过 Expando 类型支持动态属性。

而不是将模型定义为:

'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]
xs = Service.user_organizatios_with_companies(u)

organizations = [x.to_dict() for x in xs]

for x in xrange(0,len(xs)):

 organizations[x]['companies'] = xs[x].to_dict()

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)

class BaseModel(ndb.Model):
class BaseModel(ndb.Expando):

使用 Expando:

定义它

'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]
xs = Service.user_organizatios_with_companies(u)

organizations = [x.to_dict() for x in xs]

for x in xrange(0,len(xs)):

 organizations[x]['companies'] = xs[x].to_dict()

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)

class BaseModel(ndb.Model):
class BaseModel(ndb.Expando):

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


相关推荐

  • Spring部署设置openshift

    Springdeploymentsettingsopenshift我有一个问题让我抓狂了三天。我根据OpenShift帐户上的教程部署了spring-eap6-quickstart代码。我已配置调试选项,并且已将Eclipse工作区与OpehShift服务器同步-服务器上的一切工作正常,但在Eclipse中出现无法消除的错误。我有这个错误:cvc-complex-type.2.4.a:Invali…
    2025-04-161
  • 检查Java中正则表达式中模式的第n次出现

    CheckfornthoccurrenceofpatterninregularexpressioninJava本问题已经有最佳答案,请猛点这里访问。我想使用Java正则表达式检查输入字符串中特定模式的第n次出现。你能建议怎么做吗?这应该可以工作:MatchResultfindNthOccurance(intn,Patternp,CharSequencesrc){Matcherm=p.matcher…
    2025-04-161
  • 如何让 JTable 停留在已编辑的单元格上

    HowtohaveJTablestayingontheeditedcell如果有人编辑JTable的单元格内容并按Enter,则内容会被修改并且表格选择会移动到下一行。是否可以禁止JTable在单元格编辑后转到下一行?原因是我的程序使用ListSelectionListener在单元格选择上同步了其他一些小部件,并且我不想在编辑当前单元格后选择下一行。Enter的默认绑定是名为selectNext…
    2025-04-161
  • Weblogic 12c 部署

    Weblogic12cdeploy我正在尝试将我的应用程序从Tomcat迁移到Weblogic12.2.1.3.0。我能够毫无错误地部署应用程序,但我遇到了与持久性提供程序相关的运行时错误。这是堆栈跟踪:javax.validation.ValidationException:CalltoTraversableResolver.isReachable()threwanexceptionatorg.…
    2025-04-161
  • Resteasy Content-Type 默认值

    ResteasyContent-Typedefaults我正在使用Resteasy编写一个可以返回JSON和XML的应用程序,但可以选择默认为XML。这是我的方法:@GET@Path("/content")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicStringcontentListRequestXm…
    2025-04-161
  • 代码不会停止运行,在 Java 中

    thecodedoesn'tstoprunning,inJava我正在用Java解决项目Euler中的问题10,即"Thesumoftheprimesbelow10is2+3+5+7=17.Findthesumofalltheprimesbelowtwomillion."我的代码是packageprojecteuler_1;importjava.math.BigInteger;importjava…
    2025-04-161
  • Out of memory java heap space

    Outofmemoryjavaheapspace我正在尝试将大量文件从服务器发送到多个客户端。当我尝试发送大小为700mb的文件时,它显示了"OutOfMemoryjavaheapspace"错误。我正在使用Netbeans7.1.2版本。我还在属性中尝试了VMoption。但仍然发生同样的错误。我认为阅读整个文件存在一些问题。下面的代码最多可用于300mb。请给我一些建议。提前致谢publicc…
    2025-04-161
  • Log4j 记录到共享日志文件

    Log4jLoggingtoaSharedLogFile有没有办法将log4j日志记录事件写入也被其他应用程序写入的日志文件。其他应用程序可以是非Java应用程序。有什么缺点?锁定问题?格式化?Log4j有一个SocketAppender,它将向服务发送事件,您可以自己实现或使用与Log4j捆绑的简单实现。它还支持syslogd和Windows事件日志,这对于尝试将日志输出与来自非Java应用程序…
    2025-04-161