You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 12:05:59