Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Django REST Framework Security and Customization Validate Two Fields

Dimitris Kountanis
Dimitris Kountanis
626 Points

Bummer on validating 2 fields

So as the challenge asks I try to validate the 2 fields (age and parental_approval).

I checked the docs and find that to do validation that requires multiple fields, I should override the validate method. I think the syntax is fine but I must missed a piece to this logic so I get a Bummer that says 'A young player is valid without parental approval'.

I don't understand what I should change or what I'm doing wrong!

P.S I don't want the code solution, I'm searching for the logic that I don't get. So please don't copy-paste the solution, only an explanation about what I'm doing here wrong and what I need to figure out.

from rest_framework import serializers

from . import models

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

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

    def validate(self, data):
        if data['age'] < 13:
            data['parental_approval'] = True
            return data
            return data
        raise serializers.ValidationError(
            'Children under 13 require parental approval')

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
Mark Schuit
Mark Schuit
2,921 Points

Not sure if I interpret the fields correctly, but I think you need to throw the error only if both age < 13 and parental approval is false. In pseudo code:

If age < 13 and no parental approval -> raise error Else return data

Edit: To elaborate, I think your current code automatically sets the approval to true if age <13. The error now never gets raised.

2 Answers

We really want to consider that there are 3 cases here.

  1. The player is at least 13 years old: returns data
  2. The player is under 13 but has parent approval: returns data
  3. The player is under 13 and does not have parental approval: throw an error.
    def validate(self, data):
        if data['age'] >= 13: # Player is at least 13
            return data
        elif data['age'] < 13 and data['parent_approval']: # Under 13 with parent approval
            return data
            raise serializers.ValidationError('Children under 13 require parental approval') # Throw validation error

The main source of your problems is that you are only checking if the player is under 13, but not if they have parental approval. You are instead assigning data['parental_approval'] after the first condition is checked. Other than the fact that data['parental_approval'] should instead be data['parent_approval'], we actually want to be checking for the value in this field instead of directly assigning it. Even after addressing this, we need to make sure that players who are at least 13 are approved.

In observance of the Zen of Python, my sample adds an elif statement to the conditional chain to be more direct and clear when considering we are investigating several situations before determining the data is valid or invalid. This could probably be restructured, but it was pretty easy for me to read after and while writing this.

Hope this helps!

17,294 Points

Great explanation Joshua. I was able to simplify this code down a bit using "or" (just another option):

def validate(self, value): if value['age'] >= 13 or value['parent_approval']: return value raise serializers.ValidationError('Children under 13 require parental approval')