简体   繁体   English

如何将不在模型上的字段添加到django-rest-framework序列化器?

[英]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. 我有一个序列化程序,可以很好地用于GET,POST,DELETE操作。 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. 但是,对于PUT操作,用户将发回未内置到我的模型中的值,并且服务器将处理如何在模型上执行更新。 I can send the data back using Postman or Curl and it works but the browseable API still looks like this: 我可以使用Postman或Curl将数据发送回去,并且可以正常工作,但可浏览的API仍如下所示: 在此处输入图片说明

For the PUT method I want "is_winner", "num_hands_won", and "score" to show up instead of the actual model fields. 对于PUT方法,我希望显示“ is_winner”,“ num_hands_won”和“ score”,而不是实际的模型字段。 How do I do this? 我该怎么做呢? (Let me know in the comments if you need more info) (如果您需要更多信息,请在评论中告诉我)

StatisticsSerializer: 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 您可能会使用其他序列化器并将其用于您的PUT API
StatisticsUpdateSerializer: 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 而看跌期权API中使用串行或创建如图所示DRF文件中提到的例子一个新的路线在这里

@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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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