Django REST Framework TypeError: NoneType对象不可调用问题
问题描述
登录状态下访问http://127.0.0.1:8000/api/v1/content/?format=json可正常获取数据,但访问不带格式参数的http://127.0.0.1:8000/api/v1/content/时触发TypeError: 'NoneType' object is not callable;登出后访问该链接无此问题。
错误原因分析
从报错栈可追踪到核心问题:
- 不指定
format=json时,DRF默认使用Browsable API渲染器,渲染过程中会尝试生成POST请求的交互表单,此时会调用view.get_serializer()。 - 你的
ContentViewSet重写的get_serializer_class仅处理了list和retrieve两个动作,当动作属于其他场景(比如渲染表单、ModelViewSet自带的create/update等默认动作)时,该方法返回None,导致调用serializer_class(*args, **kwargs)时触发NoneType不可调用的错误。 - 登录状态下Browsable API会展示完整交互表单(包含POST操作入口),触发上述逻辑;登出后因
IsAuthenticatedOrReadOnly权限限制,表单不显示,因此不会触发错误。
解决方案
提供两种可选方案,根据业务需求选择:
方案1:限制视图集的允许动作
如果ContentViewSet仅需提供list、retrieve及LikedMixin中的自定义动作,无需支持create/update/destroy等默认ModelViewSet动作,可直接指定允许的HTTP方法或动作:
class ContentViewSet(LikedMixin, viewsets.ModelViewSet): """Вывод деталей контента""" queryset = Content.objects.filter(is_banned=False) permission_classes = (IsAuthenticatedOrReadOnly,) # 仅保留需要的HTTP方法(POST用于like/unlike动作) http_method_names = ['get', 'post'] def get_object(self): kinopoisk_id = self.kwargs.get('pk') content = get_object_or_404(Content, kinopoisk_id=kinopoisk_id, is_banned=False) return content def get_serializer_class(self): if self.action == 'list': return ContentListSerializer elif self.action == 'retrieve': return ContentDetailSerializer elif self.action == 'fans': return FanSerializer # 为like/unlike动作指定空序列化器(无需请求体) elif self.action in ['like', 'unlike']: return serializers.Serializer # 兜底返回可用序列化器 return ContentListSerializer
方案2:完善get_serializer_class的兜底逻辑
如果需要保留ModelViewSet的全部动作,或确保所有场景都有可用的序列化器,修改get_serializer_class添加兜底返回:
def get_serializer_class(self): if self.action == 'list': return ContentListSerializer elif self.action == 'retrieve': return ContentDetailSerializer elif self.action == 'fans': return FanSerializer # 若需要支持创建/更新动作,可在此处指定对应的序列化器 # elif self.action in ['create', 'update', 'partial_update']: # return ContentCreateUpdateSerializer # 兜底返回一个默认序列化器,避免返回None return ContentListSerializer
补充测试建议
修改后登录状态下访问不带format参数的链接,确认Browsable API正常渲染且无报错;若不需要Browsable API,可在项目settings的REST_FRAMEWORK配置中移除rest_framework.renderers.BrowsableAPIRenderer,但不推荐——该渲染器是开发调试的实用工具。
内容的提问来源于stack exchange,提问作者nnekkitt
相关产品推荐
相关产品推荐

