Ryan113
Ryan113

Reputation: 686

Django Rest Framework Custom Serializer Method

I'm trying to create a custom serializer method that counts the number of passed and failed quizzes from my QuizResults model. A failed quiz is under .7 and a passed quiz is .7 or over.

I want to be able to look into the Users QuizResult and count the number of passed quizzes(.7 or over). I would then duplicate the method to count the failed quizzes (under .7).

So far I don't have much idea on how to do so. I want to be able to grab the percent_correct field of the model and do a calculation and add it to a field in the serializer called "quiz_passed".

Here is my QuizResult model:

class QuizResult(models.Model):
    quiz = models.ForeignKey(Quiz)
    user = models.ForeignKey(User, related_name='quiz_parent')
    percent_correct = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(1.0)])
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
         return 'Quiz Results for : ' + self.quiz.title

Here is my serializer:

class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    todo_count = serializers.IntegerField(source='todo_parent.count', read_only=True)
    discussion_count = serializers.IntegerField(source='comment_parent.count', read_only=True)
    quiz_passed = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('todo_count', 'discussion_count', 'quiz_passed', 'username', )

    def get_quiz_passed(self, obj):
        return passed

Any help is appreciated.

Edit:

I extended the User model and added a model method like you suggested.

class Profile(User):

    def get_quizzes_passed_count(self):
        return self.quiz_parent.filter(percent_correct__gte=0.8).count()

I then added your suggestion to my ProfileSerializer.

class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    todo_count = serializers.IntegerField(source='todo_parent.count', read_only=True)
    discussion_count = serializers.IntegerField(source='comment_parent.count', read_only=True)
    num_quizzes_passed = serializers.ReadOnlyField(source="get_quizzes_passed_count")

class Meta:
    model = Profile
    fields = ('todo_count', 'discussion_count', 'num_quizzes_passed', 'username')

Unfortunately when I add this nothing appears in the framework once these have been added. Any suggestions? Thank you.

Upvotes: 3

Views: 3797

Answers (1)

YPCrumble
YPCrumble

Reputation: 28662

You can use a model method on the user model to count that user's number of passed quizzes:

class User(models.model):
    # rest of your User attributes
    def get_quizzes_passed_count(self):
        return self.quiz_parent.filter(percent_correct__gte=0.7).count()

Then add that to your serializer using a DRF ReadOnlyField to serialize that method:

class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    todo_count = serializers.IntegerField(
        source='todo_parent.count', read_only=True
    )
    discussion_count = serializers.IntegerField(
        source='comment_parent.count', read_only=True
    )
    quiz_passed = serializers.SerializerMethodField()
    num_quizzes_passed = serializers.ReadOnlyField(source="get_quizzes_passed_count")

    class Meta:
        model = User
        fields = ('todo_count', 'discussion_count', 'quiz_passed', 'username', )

    def get_quiz_passed(self, obj):
        return passed

You can duplicate this for the number of failed quizzes.

Upvotes: 4

Related Questions