使用PynamoDB查询DynamoDB索引时遇AttributeError问题求助
解决PynamoDB查询全局二级索引时的AttributeError错误
我有一个存储职位招聘详情的DynamoDB表,已配置全局二级索引recruiter_index。使用PynamoDB库编写了模型类Opening和索引类RecruiterIndex,执行查询代码时触发错误:AttributeError: 'NoneType' object has no attribute 'serialize'。
相关代码
opening.py
from pynamodb.models import Model from pynamodb.attributes import UnicodeAttribute from kink import di, inject from models.recruiter_index import RecruiterIndex @inject class Opening(Model): """ A DynamoDB Opening Table """ class Meta: table_name = "mo-bizin-travay" region = "eu-west-1" recruiter_index = RecruiterIndex() id = UnicodeAttribute(hash_key=True) title = UnicodeAttribute() posted_date = UnicodeAttribute() recruiter = UnicodeAttribute() updated_at = UnicodeAttribute()
recruiter_index.py
from pynamodb.indexes import GlobalSecondaryIndex, AllProjection from pynamodb.attributes import UnicodeAttribute class RecruiterIndex(GlobalSecondaryIndex): """ This class represents a global secondary index """ class Meta: # index_name is optional, but can be provided to override the default name index_name = "recruiter_index" read_capacity_units = 2 write_capacity_units = 1 # All attributes are projected projection = AllProjection() # This attribute is the hash key for the index # Note that this attribute must also exist # in the model recruiter = UnicodeAttribute()
main.py
def main(event, context): for item in Opening.recruiter_index.query("MCB"): print("Item queried from index: {0}".format(item))
报错栈
Traceback (most recent call last): File "/Users/mervin.hemaraju/Projects/Personal/mo-bizin-travay/runner.py", line 8, in <module> main(EVENT, CONTEXT) File "/Users/mervin.hemaraju/Projects/Personal/mo-bizin-travay/di.py", line 32, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "/Users/mervin.hemaraju/Projects/Personal/mo-bizin-travay/main.py", line 12, in main for item in Opening.recruiter_index.query("MCB"): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/mervin.hemaraju/Projects/Personal/mo-bizin-travay/.venv/lib/python3.11/site-packages/pynamodb/indexes.py", line 89, in query return self._model.query( ^^^^^^^^^^^^^^^^^^ File "/Users/mervin.hemaraju/Projects/Personal/mo-bizin-travay/.venv/lib/python3.11/site-packages/pynamodb/models.py", line 661, in query hash_key = cls._indexes[index_name]._hash_key_attribute().serialize(hash_key) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'serialize'
错误原因
这个错误是因为PynamoDB找不到索引对应的哈希键属性,导致_hash_key_attribute()返回了None,调用serialize()时自然就报错了。问题出在两处:
- 索引类里的
recruiter属性没加hash_key=True标记,PynamoDB无法识别它是索引的哈希键 - 模型里直接实例化
RecruiterIndex()的方式不对,索引没法和模型正确关联
修复方案
1. 给索引类的哈希键加标记
更新recruiter_index.py,给recruiter属性添加hash_key=True:
from pynamodb.indexes import GlobalSecondaryIndex, AllProjection from pynamodb.attributes import UnicodeAttribute class RecruiterIndex(GlobalSecondaryIndex): """ This class represents a global secondary index """ class Meta: index_name = "recruiter_index" read_capacity_units = 2 write_capacity_units = 1 projection = AllProjection() # 标记为索引的哈希键 recruiter = UnicodeAttribute(hash_key=True)
2. 修正模型中的索引定义
在Opening模型里,不要直接实例化索引,改用嵌套类的方式引用索引类:
from pynamodb.models import Model from pynamodb.attributes import UnicodeAttribute from kink import di, inject from models.recruiter_index import RecruiterIndex @inject class Opening(Model): """ A DynamoDB Opening Table """ class Meta: table_name = "mo-bizin-travay" region = "eu-west-1" # 用嵌套类关联索引,替代原来的实例化写法 class recruiter_index(RecruiterIndex): pass id = UnicodeAttribute(hash_key=True) title = UnicodeAttribute() posted_date = UnicodeAttribute() recruiter = UnicodeAttribute() updated_at = UnicodeAttribute()
3. 验证查询
修改完成后重新执行main.py的查询代码,即可正常通过全局二级索引查询数据。
内容的提问来源于stack exchange,提问作者Mervin Hemaraju
相关产品推荐
相关产品推荐

