使用Elasticsearch-dsl与DRF时遇'InnerDoc'无'pk'属性错误求助
问题原因及解决方案
错误原因
Django REST Framework的序列化器(尤其是ModelSerializer)默认会尝试读取对象的pk属性作为主键,但elasticsearch-dsl返回的InnerDoc对象(或文档实例)并没有这个属性——哪怕你在文档类里定义了id字段,序列化器依然会优先找pk,这就是报错的核心原因。另外如果你的序列化器继承了ModelSerializer,它的设计是适配Django模型的,和elasticsearch-dsl的文档对象天然不兼容。
解决方法
1. 改用基础Serializer并明确指定主键字段
放弃继承ModelSerializer,改用rest_framework.serializers.Serializer,并在序列化器里显式定义id字段,示例:
from rest_framework import serializers class OfficeSerializer(serializers.Serializer): id = serializers.CharField(read_only=True) # 其他字段按需定义 name = serializers.CharField() address = serializers.CharField()
这样序列化器会直接读取id字段,不会再寻找pk属性。
2. 给ES文档类添加pk属性
如果一定要使用ModelSerializer,可以在你的OfficeDocument类里添加一个@property方法返回id值,让序列化器能获取到pk:
from elasticsearch_dsl import Document, Keyword, Text class OfficeDocument(Document): id = Keyword() name = Text() address = Text() @property def pk(self): return self.id class Index: name = 'offices'
3. 检查查询返回的对象类型
确认PaginatedElasticSearchAPIView中results返回的是OfficeDocument实例,而非嵌套的InnerDoc。如果是嵌套文档导致的问题,需要调整查询逻辑,确保传递给序列化器的是顶层文档对象,或者针对嵌套的InnerDoc单独适配序列化器。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

