LDJ
LDJ

Reputation: 7304

Django Rest framework attributeerror

I’m working through a book that introduces the Django and Django Rest frameworks. The tutorial creates a rest API with games, categories, players and scores, with a suitable relational model between them. I’ve stumbled upon an issue when inserting a game category I get the following error:

AttributeError at /game-categories/
'GameCategory' object has no attribute 'games'
Request Method: POST
Request URL:    http://127.0.0.1:8000/game-categories/
Django Version: 1.10.5
Exception Type: AttributeError
Exception Value:    
'GameCategory' object has no attribute 'games'
Exception Location: C:\Users\user\AppData\Local\Programs\Python\Python36-32\lib\site-packages\rest_framework\fields.py in get_attribute, line 103
Python Executable:  C:\Users\user\AppData\Local\Programs\Python\Python36-32\python.exe
Python Version: 3.6.0
Python Path:    
['C:\\Python\\Django01\\gamesapi',
 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python36-32\\python36.zip',
 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python36-32\\DLLs',
 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python36-32\\lib',
 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python36-32',
 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\site-packages']
Server time:    Wed, 8 Mar 2017 09:40:42 +0000

My Game and GameCategory models are as follows:

class GameCategory(models.Model):
    name = models.CharField(max_length=200)

    class Meta:
        ordering = ('name',)

    def __str__(self):
        return self.name

class Game(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    name = models.CharField(max_length=200, blank=True, default='')
    game_category = models.ForeignKey(GameCategory, related_name='games', on_delete=models.CASCADE)
    release_date = models.DateTimeField()
    game_category = models.CharField(max_length=200, blank=True, default='')
    played = models.BooleanField(default=False)

    class Meta:
        ordering = ('name',)
    def __str__(self):
        return self.name

and the snippet of my urls.py:

urlpatterns = [
    url(r'^game-categories/$', views.GameCategoryList.as_view(),name=views.GameCategoryList.name),
    url(r'^game-categories/(?P<pk>[0-9]+)$', views.GameCategoryDetail.as_view(), name=views.GameCategoryDetail.name),

views.py:

from games.models import GameCategory
from games.models import Game
from games.models import Player
from games.models import PlayerScore    
from games.serializers import GameCategorySerializer
from games.serializers import GameSerializer
from games.serializers import PlayerSerializer
from games.serializers import PlayerScoreSerializer
from rest_framework import generics
from rest_framework.response import Response
from rest_framework.reverse import reverse

class GameCategoryList(generics.ListCreateAPIView):
    queryset=GameCategory.objects.all()
    serializer_class=GameCategorySerializer
    name='gamecategory-list'

class GameCategoryDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset=GameCategory.objects.all()
    serializer_class = GameCategorySerializer
    name = 'gamecategory-detail'

class GameList(generics.ListCreateAPIView):
    queryset=Game.objects.all()
    serializer_class = GameSerializer
    name = 'game-detail'

class GameDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset=Game.objects.all()
    serializer_class=GameSerializer
    name='game-detail'

serializers.py

from rest_framework import serializers
from games.models import GameCategory
from games.models import Game
from games.models import Player
from games.models import PlayerScore
import games.views

class GameCategorySerializer(serializers.HyperlinkedModelSerializer):
    games = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='game-detail'
    )

    class Meta:
        model = GameCategory
        fields = ('url','pk','name','games')

class GameSerializer(serializers.HyperlinkedModelSerializer):
    #We want to display the game categorys name instead of the id
    game_category = serializers.SlugRelatedField(queryset=GameCategory.objects.all(), slug_field='name')

    class Meta:
        model = Game
        fields = (
            'url',
            'game_category',
            'name',
            'release_date',
            'played'
        )

I’m still very new to Python, let alone Django, so I am struggling to source the error here from the debug information given.

Can anyone help me understand where the problem is and why?

Upvotes: 1

Views: 1825

Answers (1)

nik_m
nik_m

Reputation: 12086

How about removing HyperlinkedModelSerializer from GameCategorySerializer?

class GameCategorySerializer(serializers.ModelSerializer):
    # rest here unchanged

Check here for more.

[UPDATE]: You have a duplication inside the Game model!

game_category = models.ForeignKey(GameCategory, related_name='games', on_delete=models.CASCADE)

and

game_category = models.CharField(max_length=200, blank=True, default='')

You should rename the second game_category field to something else. Thus, the error you'are getting. GameCategorySerializer tries to handle this field (which does not have a related_name attribute) instead of the first (ForeignKey) one.

Upvotes: 1

Related Questions