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

DRF开发出现TypeError: 'type' object is not iterable错误求助

DRF API 出现 'type' object is not iterable 错误排查

我首次开发DRF API,在给Movie模型添加Reviews评分平均值计算函数后,发送GET请求时触发了'type' object is not iterable错误。之前功能都正常,搞不懂为什么Reviews和Actor会出现可迭代相关问题,附上相关代码和报错堆栈,求帮忙解决。


相关代码片段

models.py

from django.db import models
from django.contrib.auth import get_user_model

import datetime

User = get_user_model()

class Actor(models.Model):
  name = models.CharField(max_length=255)
  first_name = models.CharField(max_length=255)

class Movie(models.Model):
  title = models.CharField(max_length=255)
  description = models.CharField(max_length=255, default='Description')
  date = models.DateTimeField(default=datetime.date.today)
  created_on = models.DateTimeField(auto_now_add = True)
  actors = models.ManyToManyField(Actor)
  user = models.ForeignKey(User, on_delete=models.CASCADE)
  def average_reviews(self):
    if hasattr(self, '_average_reviews'):
      return self._average_reviews
    return self.reviews.aggregate(models.Avg('mark'))
  
class Reviews(models.Model):
  mark = models.IntegerField(default=5)
  movie = models.ForeignKey(Movie, on_delete=models.CASCADE)

views.py

from django.shortcuts import render
from django.db.models import Avg

from rest_framework import viewsets
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated

from .models import Movie, Actor, Reviews
from .serializers import MovieSerializer, ActorSerializer, ReviewsSerializer

# Create your views here.

class MovieViewSet(viewsets.ModelViewSet):
  authentication_classes = (BasicAuthentication,)
  permission_classes = (IsAuthenticated,)
  serializer_class = MovieSerializer
  def get_queryset(self):
    return Movie.objects.all().annotate(_average_reviews=Avg('reviews__mark'))
  #queryset = Movie.objects.all()

class ActorViewSet(viewsets.ModelViewSet):
  authentication_classes = (BasicAuthentication)
  permission_classes = (IsAuthenticated,)
  serializer_class = ActorSerializer,
  queryset = Actor.objects.all()

class ReviewsViewSet(viewsets.ModelViewSet):
  authentication_classes = (BasicAuthentication)
  permission_classes = (IsAuthenticated,)
  serializer_class = ReviewsSerializer,
  queryset = Reviews.objects.all()

serializers.py

from rest_framework import serializers
from .models import Movie, Actor, Reviews

class ActorSerializer(serializers.ModelSerializer):
  class Meta:
    model = Actor
    fields = '__all__'

class ReviewsSerializer(serializers.ModelSerializer):
  class Meta:
    model = Reviews
    fields = '__all__'

class MovieSerializer(serializers.ModelSerializer):
  actors = ActorSerializer(many=True)
  average_reviews = serializers.SerializerMethodField()
  def get_average_reviews(self,obj):
    return obj.average_reviews()
  class Meta:
    model = Movie
    fields = '__all__'

报错堆栈信息

Traceback (most recent call last):
  File "/home/qcouderc/.local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/qcouderc/.local/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/qcouderc/.local/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/qcouderc/.local/lib/python3.10/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/qcouderc/.local/lib/python3.10/site-packages/rest_framework/views.py", line 492, in dispatch
    request = self.initialize_request(request, *args, **kwargs)
  File "/home/qcouderc/.local/lib/python3.10/site-packages/rest_framework/viewsets.py", line 146, in initialize_request
    request = super().initialize_request(request, *args, **kwargs)
  File "/home/qcouderc/.local/lib/python3.10/site-packages/rest_framework/views.py", line 394, in initialize_request
    authenticators=self.get_authenticators(),
  File "/home/qcouderc/.local/lib/python3.10/site-packages/rest_framework/views.py", line 272, in get_authenticators
    return [auth() for auth in self.authentication_classes]
TypeError: 'type' object is not iterable
[13/Sep/2022 14:36:00] "GET /api/reviews/ HTTP/1.1" 500 16564

问题解决

核心错误点

报错直接指向get_authenticators方法的迭代操作,问题出在views.py的ActorViewSet和ReviewsViewSet两个视图集的配置错误:

  1. authentication_classes = (BasicAuthentication):缺少末尾逗号,导致这不是元组而是单个类对象,DRF尝试迭代这个类时触发'type' object is not iterable错误。
  2. serializer_class = ActorSerializer,:多了末尾逗号,导致变量变成元组,而DRF需要的是单个序列化器类,会引发后续异常。

修复后的视图集代码

class ActorViewSet(viewsets.ModelViewSet):
  authentication_classes = (BasicAuthentication,)  # 补上逗号,确保是元组类型
  permission_classes = (IsAuthenticated,)
  serializer_class = ActorSerializer  # 去掉多余逗号
  queryset = Actor.objects.all()

class ReviewsViewSet(viewsets.ModelViewSet):
  authentication_classes = (BasicAuthentication,)  # 补上逗号,确保是元组类型
  permission_classes = (IsAuthenticated,)
  serializer_class = ReviewsSerializer  # 去掉多余逗号
  queryset = Reviews.objects.all()

额外优化建议

Movie模型的average_reviews方法返回的是aggregate生成的字典(格式如{'mark__avg': 4.5}),如果想直接返回数值,可以修改方法:

def average_reviews(self):
    if hasattr(self, '_average_reviews'):
        return self._average_reviews
    avg_result = self.reviews.aggregate(models.Avg('mark'))
    return avg_result.get('mark__avg') or 0  # 处理无评论场景,返回0或None

内容的提问来源于stack exchange,提问作者Quentin Couderc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:45:41