I am new to mobile app development and I am trying to make my first app with react-native and Django rest-framework as the backend. When I try to run the server and access any model through the django-rest-framework I get
"TypeError: 'type' object is not iterable." I have tried to look up a way to solve it but every way I found online did not help.
Here is my code:
models.py
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
class Movie(models.Model):
title = models.CharField(max_length=32)
description = models.TextField()
def no_of_ratings(self):
ratings = Rating.objects.filter(movie=self)
return len(ratings)
def avg_rating(self):
sum = 0
ratings = Rating.objects.filter(movie=self)
for rating in ratings:
sum = rating.stars
if len(ratings) > 0:
return sum / len(ratings)
else:
return 0
class Rating(models.Model):
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
stars = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
class Meta:
unique_together = (('user', 'movie'))
index_together = (('user', 'movie'))
serializers.py
from rest_framework import serializer
from .models import Movie, Rating
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields =('id', 'title', 'description', 'no_of_ratings', 'avg_rating')
class RatingSerializer(serializers.ModelSerializer):
class Meta:
model = Rating
fields =('id', 'stars', 'user', 'movie')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields =('id', 'username', 'password')
extra_kwargs = {'password': {'write_only': True, 'required': True}}
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
Token.objects.create(user=user)
return user
views.py
from django.shortcuts import render
from rest_framework import viewsets, status
from .serializers import MovieSerializer, RatingSerializer, UserSerializer
from .models import Movie, Rating
from rest_framework.response import Response
from rest_framework.decorators import action
from django.contrib.auth.models import User
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission
# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class MovieViewSet(viewsets.ModelViewSet):
queryset = Movie.objects.all()
serializer_class = MovieSerializer
authentication_classes = (TokenAuthentication)
permission_classes = (IsAuthenticated)
@action(detail=True, methods=['POST'])
def rate_movie(self, request, pk=None):
if 'stars' in request.data:
movie = Movie.objects.get(id=pk)
stars = request.data['stars']
user = request.user
try:
rating = Rating.objects.get(user=user.id, movie=movie.id)
rating.stars = stars
rating.save()
serializer = RatingSerializer(rating, mamy=False)
Rating.objects.create(user=user, movie=movie, stars=stars)
response = {'message': 'Rating Updated', 'result': serializer.data}
except:
rating = Rating.objects.create(user=user, movie=movie, stars=stars)
serializer = RatingSerializer(rating, mamy=False)
response = {'message': 'Rating created', 'result': serializer.data}
return Response(response, status=status.HTTP_200_OK)
else:
response = {'message': 'you need to provide stars'}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
class RatingViewSet(viewsets.ModelViewSet):
queryset = Rating.objects.all()
serializer_class = RatingSerializer
authentication_classes = (TokenAuthentication)
permission_classes = (AllowAny)
def update(self, request, *args, **kwargs):
response = {'message': 'You cant update rating like that'}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
def create(self, request, *args, **kwargs):
response = {'message': 'You cant create rating like that'}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
How can I fix this error?
CodePudding user response:
authentication_classes
and permission_classes
must be tuple or list. When you put single class in parantheses, it will not behave with it as tuple but just one, so cannot iterate over it.
Change them as below in all your viewsets (Put an extra comma after them to show python that these parantheses demonstrate tuple):
#...
authentication_classes = (TokenAuthentication,)
permission_classes = (AllowAny,)
#...