Home > Enterprise >  TypeError: 'type' object is not iterable - DRF
TypeError: 'type' object is not iterable - DRF

Time:09-14

I'm making my first DRF api and I get a strange TypeError when I try to access to my data using a GET request, I get this error:

'type' object is not iterable

All working until I add the function for get the average of Reviews.mark in Movie. I not understand why Reviews and Actors are iterable and if you can explain it to me it's cool !

Here are some code snippets bellow.

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__'

I also leave the Traceback for more informations:

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

Thanks for your help

CodePudding user response:

You should add comma after authentication class to make python understand that this is tuple:

class ActorViewSet(viewsets.ModelViewSet):
  authentication_classes = (BasicAuthentication,)

Or you can just use list:

class ActorViewSet(viewsets.ModelViewSet):
  authentication_classes = [BasicAuthentication]
  • Related