Creating serializer to display correct data

2019-08-19 23:44发布

问题:

I have 4 models. User, Question, Choice, and Voting. This is basically a polls app I'm trying to create. A question can have many choices. The Voting model tracks what each user chose as their answer.

What I'd like to do is retrieve all the questions and also check what choice the logged in user selected for each question. Here's the models:

class Question(models.Model):
    user            = models.ForeignKey(User, on_delete=models.CASCADE)
    status          = models.CharField(max_length=200)
    total_votes     = models.IntegerField(default=0)

class Choice(models.Model):
    question    = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice      = models.CharField(max_length=120)
    vote_count  = models.IntegerField(default=0)

class Voting(models.Model):
    user    = models.ForeignKey(User, on_delete=models.CASCADE)
    choice  = models.ForeignKey(Choice, on_delete=models.CASCADE)

Here's how I want the data displayed:

{
    user: 2
    status: "Hello"
    total_votes: 101
    choices: [
                {
                    "id": 2,
                    "choice": "first choice",
                    "vote_count": 31,
                    "question": 3
                },
                {
                    "id": 4,
                    "choice": "second choice",
                    "vote_count": 70,
                    "question": 3
                }
            ],
    choice_selected: 2
}

In the data above, the logged in user selected choice 2 in this specific question.

Edit: My attempt to add serializer, but displays Object of type 'Voting' is not JSON serializable

class ChoiceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Choice
        fields = '__all__'

class QuestionSerializer(serializers.ModelSerializer):
    choices = ChoiceSerializer(source='choice_set', many=True)
    class Meta:
        model = Question
        fields = '__all__'


class GetProfileQuestions(ListAPIView):
    serializer_class = QuestionSerializer

    def get_queryset(self):
        return Question.objects.all()

This query successfully prints out each question and its choices. However, how do I make it so that it also prints out which choice the user selected for each question?

class VotingSerializer(serializers.ModelSerializer):

    class Meta:
        model = Voting
        fields = '__all__'    


class ChoiceSerializer(serializers.ModelSerializer):
    votes = VotingSerializer(source='voting_set', many=True)
    class Meta:
        model = Choice
        fields = '__all__'


class QuestionSerializer(serializers.ModelSerializer):
    choices = ChoiceSerializer(source='choice_set', many=True)
    choice_selected = serializers.SerializerMethodField()
    class Meta:
        model = Question
        fields = '__all__'

    def get_choice_selected(self, obj):
        choice_selected = Voting.objects.filter(choice__question=obj.id).filter(user=obj.user)
        return choice_selected

回答1:

I think you will want this in your QuestionSerializer class

 choice_selected = serializers.SerializerMethodField()

and define a method that looks something like this in QuestionSerializer …

def get_choice_selected(self, obj):
        choice_selected = Voting.objects.filter(choice__question=obj.id).filter(user=obj.user)
        return choice_selected

The above is untested.