6

階層型リソースを備えた django-rest-framework REST API があります。/v1/objects/<pk>/subobjects/POST でサブオブジェクトを作成し、新しいサブオブジェクトの外部キーをpk、ペイロードに入れることなく、URL から kwargに自動的に設定できるようにしたいと考えています。現在、シリアライザーは外部キーがペイロードにあると想定しているため、400 エラーを引き起こしていますobjectが、それもオプションと見なすべきではありません。サブオブジェクトの URL は(それを識別するために親のキーは必要ないため) であるため、既存のリソース/v1/subobjects/<pk>/が必要な場合でも必要です。PUT

/v1/subobjects/サブオブジェクトを追加するためにペイロードに親を付けてPOST するようにする必要がありますか、pkそれとも URL からシリアライザーに kwarg を渡すクリーンな方法がありますか? 私は使用HyperlinkedModelSerializerしていますModelViewSet私のそれぞれの基本クラスとして。これを行うための推奨される方法はありますか?これまでのところ、私が持っていた唯一のアイデアは、ViewSet を完全に再実装し、get_default_fields() が ViewSet から渡されたディクショナリから取得され、その kwargs によって取り込まれたカスタム Serializer クラスを作成することでした。これは、私が完全にありふれたものだと思っていた何かにかなり関与しているように見えるので、何かが欠けていると思わずにはいられません。私がこれまでに見た書き込み可能なエンドポイントを持つすべての REST API には、この種の URL ベースの引数推論があります。

4

4 に答える 4

1

これを解決するために私が行ったことは次のとおりですが、これは非常に一般的な URL パターンであるため、より一般的な方法で解決できるとよいでしょう。create最初に、メソッドを再定義するビューセットの mixin を作成しました。

class CreatePartialModelMixin(object):
    def initial_instance(self, request):
        return None

    def create(self, request, *args, **kwargs):
        instance = self.initial_instance(request)
        serializer = self.get_serializer(
            instance=instance, data=request.DATA, files=request.FILES,
            partial=True)

        if serializer.is_valid():
            self.pre_save(serializer.object)
            self.object = serializer.save(force_insert=True)
            self.post_save(self.object, created=True)
            headers = self.get_success_headers(serializer.data)
            return Response(
                serializer.data, status=status.HTTP_201_CREATED,
                headers=headers)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

ほとんどの場合、 からコピーして貼り付けますが、部分的な逆シリアル化を実行するように設定されたシリアライザーの開始点を提供するために、サブクラスでオーバーライドできるメソッドをCreateModelMixin定義します。initial_instance次に、たとえば、次のことができます。

class SubObjectViewSet(CreatePartialModelMixin, viewsets.ModelViewSet):
    # ....

    def initial_instance(self, request):
        instance = models.SubObject(owner=request.user)
        if 'pk' in self.kwargs:
            parent = models.MainObject.objects.get(pk=self.kwargs['pk'])
            instance.parent = parent
        return instance

(モデルに関連付けるために pk を実際に実行する必要がないことはわかっています.getが、私の場合は、公開 API の主キーではなくスラッグを公開しています)

于 2013-08-04T08:02:24.857 に答える
0

少し遅いかもしれませんが、この drf ネストされたルーター ライブラリがその操作に役立つと思います。

于 2016-03-19T23:58:11.723 に答える