Django REST Framework:将上下文传递给嵌套的序列化程序

时间:2016-05-27 12:40:01

标签: django-rest-framework

我有一对父子模型/序列化/视图集 - 工具和工具输入:

models.py:

class Tool(models.Model):
    id = models.CharField(max_length=10000, primary_key=True, default=uuid.uuid4, editable=False)
    base_command = jsonfield.JSONField(verbose_name="baseCommand")

class ToolInput(models.Model):
    tool = models.ForeignKey(Tool, related_name="inputs", on_delete=models.CASCADE)
    id = models.CharField(max_length=10000, primary_key=True)
    label = models.CharField(max_length=10000, null=True, blank=True)
    description = models.CharField(max_length=10000, null=True, blank=True)
    type = jsonfield.JSONField()

serializers.py

class ToolSerializer(WritableNestedModelSerializerMixin,
                     serializers.HyperlinkedModelSerializer):
    id = serializers.CharField()
    inputs = ToolInputSerializer(many=True)
    baseCommand = serializers.JSONField(source="base_command")

    class Meta:
        model = Tool
        fields = ('id', 'inputs', 'baseCommand')

class ToolInputSerializer(WritableNestedModelSerializerMixin,
                          serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ToolInput
        fields = ('id', 'label', 'description', 'type')

views.py:

class ToolViewSet(viewsets.ModelViewSet):
    queryset = Tool.objects.all()
    lookup_field = 'id'
    serializer_class = ToolSerializer

class ToolInputViewSet(viewsets.ModelViewSet):
    lookup_field = 'id'
    serializer_class = ToolInputSerializer

    def get_queryset(self):
        tool_id = self.kwargs['tool_id']
        return ToolInput.objects.filter(tool_id=tool_id)

    def get_serializer_context(self):
        context = super(ToolInputViewSet, self).get_serializer_context()
        context["tool"] = Tool.objects.get(id=self.kwargs['tool_id'])
        return context

如您所见,我使用ToolInputSerializer作为ToolInputViewSet的独立序列化程序和ToolViewSet中的嵌套序列化程序。

ToolInputSerializer用作ToolViewSet中的嵌套序列化程序时,它会以某种方式自动接收tool参数的值,并将其分配给ToolInput模型的tool领域(顺便说一下,从架构的角度来看,我认为这是一个完全错误的行为 - tool上根本没有ToolInputSerializer这样的领域,而DRF正在填补相应模型的领域 - 它应该拯救IMO出现Field Does Not Exist错误,并且至少需要序列化程序上的只写字段tool

但是当我在ToolInputViewSet中将其用作独立序列化程序时,我想将ToolInput模型的tool字段的值分配给Tool实例,由{tool_id确定1}} url参数,由ToolInputViewSet在kwargs中接收。

我正在尝试使用序列化程序上下文传递该字段的值,覆盖ToolInputViewSet.get_serializer_context()方法,但它无法正常工作。怎么做得好?

旁注:我已经厌倦了DRF的上下文处理的混乱和不一致,非均匀的自动化,这些处理可以穿透Model-Serializer-Field-View架构的各个层次。它确实需要更明确和可定制。

1 个答案:

答案 0 :(得分:0)

至于背景,我仍然不知道如何使其发挥作用。

至于嵌套序列化程序的工作方式,这很糟糕:正如您所看到的,我从自定义WritableNestedModelSerializerMixin继承了所有ViewSet,我已覆盖create()和{{1使用嵌套数据结构的方法,所以这是我的修补。

因此,作为一种解决方法,我创建了一个单独的update()并修改了ToolInputViewSet,将缺少的StandaldonToolInputSerializer字段添加到序列化程序,并使用工具参考自动修补tool

request.data

serializers.py

class StandaloneToolInputSerializer(serializers.HyperlinkedModelSerializer): tool = serializers.PrimaryKeyRelatedField( write_only=True, many=False, queryset=Tool.objects.all() ) inputBinding = serializers.JSONField(source="input_binding") class Meta: model = ToolInput fields = ('id', 'tool', 'label', 'description', 'type', 'inputBinding')

views.py