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]