简体   繁体   中英

How do I add a field to a django-rest-framework serializer that isn't on my model?

I have a serializer that works fine for the GET, POST, DELETE actions. It exposes the model fields that I want. However for the PUT action, the user will send back values that aren't built into my models and the server will deal with how to perform the update on the model. I can send the data back using Postman or Curl and it works but the browseable API still looks like this: 在此处输入图片说明

For the PUT method I want "is_winner", "num_hands_won", and "score" to show up instead of the actual model fields. How do I do this? (Let me know in the comments if you need more info)

StatisticsSerializer:

class StatisticsSerializer(serializers.ModelSerializer):
    # pk = serializers.IntegerField(required=False)
    class Meta:
        model = Statistics
        fields = [
            'url',
            'games_won',
            'hands_won',
            'games_played',
            'high_score',
            'low_score',
        ]

Statistics Model:

class Statistics(models.Model):
    # Define model fields:
    user = models.OneToOneField(User, primary_key=True)
    games_won = models.IntegerField(null=True, blank=True)
    hands_won = models.IntegerField(null=True, blank=True)
    games_played = models.IntegerField(null=True, blank=True)
    high_score = models.IntegerField(null=True, blank=True)
    low_score = models.IntegerField(null=True, blank=True)

    def __str__(self):
        return str(self.pk)

    def increment_games_won(self, is_winner):
        if is_winner is True:
            self.games_won = self.games_won + 1
        return self.games_won

    def add_to_hands_won(self, num_hands_won):
        if num_hands_won > 0 and num_hands_won < 8:
            self.hands_won = self.hands_won + num_hands_won
        return self.hands_won

    def increment_games_played(self):
        self.games_played = self.games_played + 1
        return self.games_played

    def new_high_score(self, score):
        if score > self.high_score:
            self.high_score = score
        return self.high_score

    def new_low_score(self, score):
        if score < self.low_score:
            self.low_score = score
        return self.low_score

Statistics ViewSet:

class StatisticsViewSet(DefaultsMixin, viewsets.ModelViewSet):
    queryset = Statistics.objects.all()
    serializer_class = StatisticsSerializer
    filter_class = StatisticsFilter
    search_fields = ('pk', 'user')
    ordering_fields = ('games_won', 'hands_won', 'games_played', 'high_score', 'low_score')

    def update(self, request, pk=None):
        stats = self.get_object()

        stats.increment_games_won(request.data['is_winner'])
        stats.add_to_hands_won(request.data['num_hands_won'])
        stats.increment_games_played()
        stats.new_low_score(request.data['score'])
        stats.new_high_score(request.data['score'])
        stats.save()

        serialized_stats = StatisticsSerializer(stats, context={'request': request}).data
        return Response(serialized_stats)

You could probably use another Serializer and use it for you PUT API
StatisticsUpdateSerializer:

class StatisticsUpdateSerializer:
    is_winner = ...
    num_hands_won = ...
    score = ...

And use this serializer in the PUT API or create a new route as shown in the example mentioned in the DRF documentation here

@detail_route(methods=['post'])
def set_password(self, request, pk=None):
    user = self.get_object()

    // Use your serializer below
    serializer = PasswordSerializer(data=request.data)

    if serializer.is_valid():
        user.set_password(serializer.data['password'])
        user.save()
        return Response({'status': 'password set'})
    else:
        return Response(serializer.errors,
                        status=status.HTTP_400_BAD_REQUEST)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM