Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Django REST Framework Security and Customization Add Custom Field

David Axelrod
David Axelrod
36,073 Points

How to properly access the scores average

Tried several ways now. I think my method names match up to field names and my return logic is there so i think it must have something to do with how im accessing the scores data.

Thanks!

scorekeeper/serializers.py
from django.db.models import Avg

from rest_framework import serializers

from . import models


class GameSerializer(serializers.ModelSerializer):
    average_score = serializers.SerializerMethodField()

    class Meta:
        fields = ('id', 'name','average_score')
        model = models.Game

    def get_average_score(self, obj):
        #like hint in question
        #av = Game.scores.all().aggregate(Avg('scores')).get('scores__avg')

        #through models.py
        av = models.Game.scores.all().aggregate(Avg('scores')).get('scores__avg')

        #all the game objects averaged on score
        #av = models.Game.objects.all().aggregate(Avg('scores')).get('scores__avg')

        #dont think obj has the Game atrrib as its not a field name
        #av = obj.Game.scores.all().aggregate(Avg('scores')).get('scores__avg')
        if av is None:
            return 0
        return av


class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ('id', 'name', 'age', 'parent_approval')
        model = models.Player

    def validate(self, data):
        if data['age'] < 13 and not data['parent_approval']:
            raise serializers.ValidationError(
                "Children under 13 require parental approval"
            )
        return data


class ScoreSerializer(serializers.ModelSerializer):
    game = serializers.HyperlinkedRelatedField(
        read_only=True, view_name='apiv2:game-detail')
    player = serializers.HyperlinkedRelatedField(
        read_only=True, view_name='apiv2:player-detail')

    class Meta:
        fields = ('id', 'game', 'player', 'score')
        model = models.Score
David Axelrod
David Axelrod
36,073 Points

Oh my golly gosh gee willickers

Went back and rewatched the vid.

obj is the representation of the Game model that is passed to the serializer which has a scores attribute!

weeeeeeeee Thanks for the great course Chris and Kenneth!!

1 Answer

Daniel Muchiri
Daniel Muchiri
15,407 Points

After spending over 2 hours searching for a solution, this worked for me:

class GameSerializer(serializers.ModelSerializer):
    average_score = serializers.SerializerMethodField()
    class Meta:
        fields = ('id', 'name', 'average_score')
        model = models.Game

    def get_average_score(self, obj):
        average = obj.scores.all().aggregate(Avg('score')).get('score__avg')
        if average == None:
            return 0
        return average
David Axelrod
David Axelrod
36,073 Points

Yup thats what I got too!

Joseph Beltrami
Joseph Beltrami
5,292 Points

This actually passes if you exclude the if average == None condition.