Django Rest Framework SerializerMethodField仅在GET请求上

时间:2018-07-30 19:51:11

标签: django django-rest-framework

我的DRF后端在这里遇到了一些障碍。

我正在使用某些型号的选项填充字段。

我对一个模型有外键要求。创建模型时,我想将其保存在外来ID下。

当我请求模型时,我想要具有选择字段映射到的模型。

我能够使用SerializerMethodField做到这一点,但是,当我尝试创建模型时,由于该块无效,因此出现400错误。如果删除SerializerMethodField,则可以保存,但可以从请求中获取存储在数据库中的数字。

任何帮助将不胜感激。

class BlockViewSet(ModelViewSet):
    model = apps.get_model('backend', 'Block')
    queryset = model.objects.all()
    serializer_class = serializers.BlockSerializer
    permissions = ('All',)

    def create(self, request, format=None):
        data = request.data 
        data['user'] = request.user.id
        data['goal'] = WorkoutGoal.objects.get(goal=data['goal']).id
        block = serializers.BlockSerializer(data=data, context={'request': request})
        if block.is_valid():
            new_block = block.save()
            return Response({'block': {'name': new_block.name, 'id': new_block.id}}, status=status.HTTP_201_CREATED)
        else:
            return Response(block.errors, status=status.HTTP_400_BAD_REQUEST)

class WorkoutGoalSerializer(serializers.ModelSerializer):
    class Meta:
        model = apps.get_model('backend', 'WorkoutGoal')
        fields = ('goal',)

    goal = serializers.SerializerMethodField(read_only=True, source='get_goal')

    def get_goal(self, obj):
        return dict(WorkoutGoal.GOALS).get(obj.goal)

class BlockSerializer(serializers.ModelSerializer):
    workout_count = serializers.IntegerField(required=False)
    completed_workouts = serializers.IntegerField(required=False)
    goal = WorkoutGoalSerializer()

    class Meta:
        model = apps.get_model('backend', 'Block')
        read_only_fields = ('workout_count', 'completed_workouts')
        fields = read_only_fields + ('id', 'name', 'user', 'created', 'goal')

上面的代码返回正确的选择,但我无法保存在上面。删除goal = WorkoutGoalSerializer(),它会保存,但不会返回映射的选择。

2 个答案:

答案 0 :(得分:2)

我认为这会像魅力一样

class WorkoutGoalSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if 'request' in self.context and self.context['request'].method == 'GET':
            self.fields['goal'] = serializers.SerializerMethodField(read_only=True, source='get_goal')

    class Meta:
        model = apps.get_model('backend', 'WorkoutGoal')
        fields = ('goal',)

    goal = serializers.SerializerMethodField(read_only=True, source='get_goal')  # remove this line

    def get_goal(self, obj):
        return dict(WorkoutGoal.GOALS).get(obj.goal)

如何工作?
如果使用的方法是 goal ,它将使用 SerializerMethodField 重新启动 GET 字段。 。

记住一件事,您应该删除该行

goal = serializers.SerializerMethodField(read_only=True, source='get_goal')

答案 1 :(得分:0)

serializers.py

Microsoft.EntityFrameworkCore.Design

views.py

class BlockCreateSerializer(serializers.ModelSerializer):
    workout_count = serializers.IntegerField(required=False)
    completed_workouts = serializers.IntegerField(required=False)

    class Meta:
        model = apps.get_model('backend', 'Block')
        read_only_fields = ('workout_count', 'completed_workouts')
        fields = read_only_fields + ('id', 'name', 'user', 'created', 'goal')

class BlockSerializer(serializers.ModelSerializer):
    workout_count = serializers.IntegerField(required=False)
    completed_workouts = serializers.IntegerField(required=False)
    goal = WorkoutGoalSerializer()

    class Meta:
        model = apps.get_model('backend', 'Block')
        read_only_fields = ('workout_count', 'completed_workouts')
        fields = read_only_fields + ('id', 'name', 'user', 'created', 'goal')

覆盖class BlockViewSet(ModelViewSet): model = apps.get_model('backend', 'Block') queryset = model.objects.all() serializer_class = serializers.BlockSerializer permissions = ('All',) def get_serializer_class(self): if self.action == 'create': return serializers.BlockCreateSerializer else: return self.serializer_class def create(self, request, format=None): data = request.data data['user'] = request.user.id data['goal'] = WorkoutGoal.objects.get(goal=data['goal']).id block = self.get_serializer(data=data) if block.is_valid(): new_block = block.save() return Response({'block': {'name': new_block.name, 'id': new_block.id}}, status=status.HTTP_201_CREATED) else: return Response(block.errors, status=status.HTTP_400_BAD_REQUEST) ,以针对get_serializer_class和其他操作(serializer_class)返回不同的create