Appengine对象无'_projection'属性,ndb.KeyProperty判断报错原因咨询
解决从db.Model迁移到ndb.Model后KeyProperty判断及_projection属性报错问题
我来帮你拆解这两个报错的根源,以及对应的解决办法:
一、if ad.ndb_usr:判断报错的原因
在ndb里,ndb.KeyProperty的默认值不是None,而是一个空的ndb.Key()对象——这和你之前用的db.KeyProperty逻辑完全不一样。直接用if判断的话,空Key会被Python视为True,如果你的代码逻辑是“当属性未设置时执行某操作”,这个判断就完全反了;而且如果后续你用这个空Key去调用get()之类的方法,还会触发无效Key的报错。
二、“Appengine object has no attribute '_projection'”错误的原因
这个错误几乎都是**投影查询(projection query)**导致的:当你用ndb做投影查询时,只会加载你指定的属性,其他属性不会被初始化。如果你访问了一个不在投影列表里的属性(比如你的ndb_usr),ndb内部会尝试检查实体的_projection属性来确认哪些属性是被加载的,但如果实体的初始化状态异常(比如从db迁移过来的实体没有正确适配ndb的投影机制,或者你手动构造了实体但没处理投影信息),就会抛出这个属性不存在的错误。
对应的解决办法
1. 修正KeyProperty的判断逻辑
把原来的if ad.ndb_usr:改成以下两种方式之一,根据你的需求选择:
- 如果只是想判断Key是否被正确设置(非空):
if ad.ndb_usr and ad.ndb_usr.id(): # Key有效,执行后续操作 pass
- 如果需要确认Key对应的实体确实存在:
user_entity = ad.ndb_usr.get() if user_entity: # 实体存在,执行操作 pass
2. 解决_projection属性缺失的问题
- 如果你确实需要用投影查询:确保把
ndb_usr加入到投影列表中,比如:
# 查询时指定需要加载的属性,包括ndb_usr ads = Ad.query().fetch(projection=['ndb_usr', 'title', 'other_required_field'])
- 如果不需要投影查询:直接去掉
projection参数,获取完整的实体对象,这样所有属性都会被正常加载:
ads = Ad.query().fetch()
- 额外注意:从db.Model迁移到ndb.Model时,不要混合使用db和ndb的查询/操作(比如用db的API获取实体后转成ndb实体),这会导致实体内部状态混乱,触发各种奇怪的报错。
内容的提问来源于stack exchange,提问作者Niklas Rosencrantz
相关产品推荐
相关产品推荐

