Django调用get_beneficiary时出现TypeError: unhashable type: 'slice'错误求排查
错误原因
TypeError: unhashable type: 'slice'报错由以下核心问题导致:
- Django REST Framework 的
GenericViewSet要求get_queryset方法必须返回 Django QuerySet 对象,你当前重写的方法返回的是自定义字典结构 - DRF 内部处理列表查询的分页、排序逻辑时,会对
get_queryset返回的结果执行切片操作(格式为queryset[起始索引:结束索引]),字典不支持切片操作,且切片对象无法作为字典的key,因此抛出该错误 - 额外存在性能问题:
get_beneficiary方法中遍历受益人数据时,每次循环都单独执行一次数据库count查询,N个受益人会产生N次额外数据库查询,存在N+1性能缺陷。
修复方案
根据业务需求可选以下两种修复方式:
方案1:保留自定义返回结构,调整逻辑位置
不要重写get_queryset方法,将自定义返回逻辑放到list方法中实现:
class ListView(ResponseViewMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): serializer_class = CourseFilterSerializer queryset = Course.objects.all() def list(self, request, *args, **kwargs): common_data = self.get_queryset() course_beneficiaries = get_beneficiary(common_data) return Response({ "course_beneficiaries": course_beneficiaries, })
如果需要同时返回原Course列表数据,可以调整为:
def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) course_data = self.get_paginated_response(serializer.data).data else: serializer = self.get_serializer(queryset, many=True) course_data = serializer.data course_beneficiaries = get_beneficiary(queryset) course_data["course_beneficiaries"] = course_beneficiaries return Response(course_data)
方案2:优化统计逻辑,解决N+1性能问题
使用Django聚合查询一次性统计所有受益人的关联课程数,无需循环查询数据库:
from django.db.models import Count def get_beneficiary(): # 注:Count的参数为Course模型中关联Beneficiary外键的related_name值,默认未设置时为course_set beneficiary_list = Beneficiary.objects.annotate( course_count=Count('course_set') ).values('beneficiary_name', 'course_count') return [ {"name": item["beneficiary_name"], "count": item["course_count"]} for item in beneficiary_list ]
内容的提问来源于stack exchange,提问作者user15361826
相关产品推荐
相关产品推荐

