草庐IT

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

codeneng 2023-03-28 原文

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

的密钥

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

1
2
3
4
5
6
7
8
9
'organizations': [
  {
    'name': 'TEST'
    'companies': [ {company1}, {company2}]
  },
  {
    ...
  }
]

我这样做

1
2
3
4
5
6
7
  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]

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

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

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

1
2
3
4
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()

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

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

从 google.appengine.ext 导入 ndb
导入实用程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 通过 Expando 类型支持动态属性。

而不是将模型定义为:

1
class BaseModel(ndb.Model):

使用 Expando:

定义它

1
class BaseModel(ndb.Expando):

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

有关关于 python:将属性动态附加到 ndb.Model 的实例并将它们放在 to_dict() 表示中的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  3. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  4. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  7. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  8. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

  9. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  10. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

随机推荐