2016-05-27 33 views
1

私は親子モデル/シリアライザ/ビューセットのペアました - ツールとToolInput:ジャンゴRESTフレームワーク:ネストされたシリアライザにコンテキストを渡す

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 

ご覧のとおり、ToolInputViewSetのスタンドアロンシリアライザとして、ToolViewSetのネストシリアライザとして、ToolInputSerializerを使用します。 ToolInputSerializerToolViewSetにネストされたシリアライザとして使用する場合

、それは何らかの形で自動的にtool引数の値を受け取り、ToolInputモデルのtoolフィールドに割り当てます(ちなみに、私はそれはアーキテクチャの観点から、完全に間違っ行動だと感じます - のようなフィールドはありません。ToolInputSerializerにあり、DRFはそれぞれのモデルのフィールドを満たしています。Field Does Not ExistエラーIMOで救済され、少なくともシリアライザでは書き込み専用フィールドtoolが必要です。

しかし、私はToolInputViewSetで、スタンドアロンのシリアライザとして使用する場合、私はkwargsからでToolInputViewSetで受信しtool_id urlパラメータによって決定ToolインスタンスにToolInputモデルのtoolフィールド、、の値を割り当てます。

ToolInputViewSet.get_serializer_context()メソッドをオーバーライドするシリアライザコンテキストでそのフィールドの値を渡そうとしていますが、機能しません。どのようにそれを正しく行うには?


追記:私はモデルシリアライザ・フィールド・ビューアーキテクチャの層を貫通DRFのコンテキスト取り扱いの乱雑と矛盾し、不均一なオートマジックのかなり疲れています。それはもっと明白でカスタマイズ可能である必要があります。

答えて

0

文脈に関しては、私はまだそれを動作させる方法を知らない。シリアライザがどのように働くか、ネストされたためのよう

、これが私の悪いです:あなたが見ることができるように、私は、ネストされたデータ構造で動作するようにcreate()update()メソッドをオーバーライドしてきた私のカスタムWritableNestedModelSerializerMixin、からすべてのビューセットを継承するので、これはあります私の変態。

そうでは、回避策として、私は、シリアライザに不足しているtoolフィールドを追加すると、自動的にツールを参照してrequest.dataにパッチを適用、別々のStandaldonToolInputSerializerを作成し、ToolInputViewSetを修正:

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

class ToolInputViewSet(viewsets.ModelViewSet): 
    ''' 
    Describes a Tool input. 
    ''' 
    lookup_field = 'id' 
    serializer_class = StandaloneToolInputSerializer 

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

    def create(self, request, *args, **kwargs): 
     request.data["tool"] = self.kwargs['tool_id'] 
     return super(ToolInputViewSet, self).create(request, *args, **kwargs) 

    def update(self, request, *args, **kwargs): 
     request.data["tool"] = self.kwargs['tool_id'] 
     return super(ToolInputViewSet, self).update(request, *args, **kwargs) 
関連する問題