ビューセットのメソッドを無効にする、django-rest-framework


124

ViewSets リスト、取得、作成、更新、削除などの自動メソッドがあります...

私はそれらのいくつかを無効にしたいと思います、そして私が思いついた解決策はおそらくOPTIONSそれらが許可されていると述べているのでおそらく良いものではありません。

これを正しい方法で行う方法についてのアイデアはありますか?

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer

    def list(self, request):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
    def create(self, request):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)

回答:


250

の定義ModelViewSetは次のとおりです。

class ModelViewSet(mixins.CreateModelMixin, 
                   mixins.RetrieveModelMixin, 
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet)

では、を拡張するのModelViewSetではなく、必要なものだけを使用してみませんか?だから例えば:

from rest_framework import viewsets, mixins

class SampleViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    viewsets.GenericViewSet):
    ...

このアプローチでは、ルーターは含まれているメソッドのルートのみを生成する必要があります。

参照

ModelViewSet


@SunnySydeUpこれを試してみると、ルーターはリストビューのルートを生成しているようですが、ViewSetがリクエストの処理方法を認識していないため、ルーターは404を返します。これはあなたが期待したことですか?
スティーブジャリム14

3
必要なミックスインのみを使用することで、GET、POST、PUT、DELETEメソッドを無効にできますが、ルーターを使用している場合は、PATCHメソッドを特に無効にする方法を見つけることができませんでした。
ムニーブアフマド2015

3
@MuneebAhmad PATCHメソッドはから有効になりUpdateModelMixinます。パッチを使用せずにアップデートを使用したい場合は、現在2つの方法が考えられます。ビューで許可されているメソッドをオーバーライドして「パッチ」を削除するか、partial_updateメソッドをオーバーライドしてを呼び出すことができますhttp_method_not_allowed(request, *args, **kwargs)。私はこれをテストしていないので、それが機能するかどうかは
わかり

1
@JulioMarins参照を追加しました。これがあなたが望んでいたものかどうかはわかりません。
SunnySydeUp 2016年

1
誰かが読み取り専用のビューセットを作成したい場合は、を使用できますclass SampleViewSet(viewsets.ReadOnlyModelViewSet)
Bikash kharel

133

ViewSetで引き続き使用viewsets.ModelViewSetおよび定義できhttp_method_namesます。

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer
    http_method_names = ['get', 'post', 'head']

を追加するとhttp_method_namesputやを実行できなくなりpatchます。

あなたputがしたいがしたくないpatch場合は、保つことができますhttp_method_names = ['get', 'post', 'head', 'put']

内部的には、DRFビューはDjango CBVから​​拡張されています。Django CBVには、http_method_namesという属性があります。したがって、DRFビューでもhttp_method_namesを使用できます。

[恥知らずなプラグイン]:この回答が役に立った場合は、https: //www.agiliq.com/blog/2019/04/drf-polls/のDRFに関する私の一連の投稿を気に入っていただけることでしょう。


16
この方法の問題は、リストまたは取得を無効にする方法ではありません。両方を無効にするか、どちらも無効にする必要があります
Fuad

1
getとheadを含めた後でも、これは機能しませんでした
RunLoop

これは私にとってdjango 1.9で動作します。素晴らしいソリューション。ユーザーが別の方法でGETリクエストを実行できるリスクはありますか?
Ycon、2016年

幻想的なソリューション。上の作品python3Django 1.10うまく。
ウルダ、

2
ミックスインの継承を変更してPATCHを含めることができなかったため、この方法を選択しました。ただし、これらはどちらも実装であるため、PUTは変更しませんでした mixins.UpdateModelMixin
ThatsAMorais

5

この投稿は久しぶりですが、実際にはこれらの機能を無効にする方法であることが突然わかりました。views.pyで直接編集できます。

ソース:https : //www.django-rest-framework.org/api-guide/viewsets/#viewset-actions

from rest_framework import viewsets, status
from rest_framework.response import Response

class NameWhateverYouWantViewSet(viewsets.ModelViewSet):

    def create(self, request):
        response = {'message': 'Create function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

    def update(self, request, pk=None):
        response = {'message': 'Update function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

    def partial_update(self, request, pk=None):
        response = {'message': 'Update function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

    def destroy(self, request, pk=None):
        response = {'message': 'Delete function is not offered in this path.'}
        return Response(response, status=status.HTTP_403_FORBIDDEN)

これは望ましい方法です。
デジタケ

HTTP_400_BAD_REQUESTがauthに関連していない場合、ここではより適切だと思います。
サンティアゴマガリニョス

4

DRFビューセットからPUTメソッドを無効にしようとしている場合は、カスタムルーターを作成できます。

from rest_framework.routers import DefaultRouter

class NoPutRouter(DefaultRouter):
    """
    Router class that disables the PUT method.
    """
    def get_method_map(self, viewset, method_map):

        bound_methods = super().get_method_map(viewset, method_map)

        if 'put' in bound_methods.keys():
            del bound_methods['put']

        return bound_methods

ルーターでメソッドを無効にすることで、APIスキーマのドキュメントが正しくなります。


部分パッチはDRF内に正しく実装されていないため、ここで説明されている方法でグローバルに削除することをお勧めします
oden

1

DRFでViewSetの「DELETE」メソッドを無効にする方法

class YourViewSet(viewsets.ModelViewSet):
    def _allowed_methods(self):
        return [m for m in super(YourViewSet, self)._allowed_methods() if m not in ['DELETE']]

PSこれは、必要なすべてのメソッドを明示的に指定するよりも信頼性が高いため、いくつかの重要なメソッドOPTIONS、HEADなどを忘れる可能性が低くなります。

デフォルトのDRFのPPSには http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']


superクラスレベルで呼び出すことはできませんself
有効名

0

Django Rest Framework 3.xx ModelViewSetでは、as_viewメソッドにディクショナリを渡すことで、有効にするすべてのメソッドを有効にすることができます。このディクショナリでは、キーに要求タイプ(GET、POST、DELETEなど)が含まれている必要があり、値には対応するメソッド名(リスト、取得、更新など)が含まれている必要があります。たとえば、Sampleモデルを作成または読み取りたいが、モデルは変更したくないとします。あなたがしたいこと、それはそうlistretrieveおよびcreate有効する方法(とあなたが他の人が無効にすることにしたいです。)

urlpatterns次のようにパスを追加するだけです。

path('sample/', SampleViewSet.as_view({
    'get': 'list',
    'post': 'create'
})),
path('sample/<pk>/', SampleViewSet.as_view({  # for get sample by id.
    'get': 'retrieve'
}))

上記のルーティング設定にはdeleteand putリクエストがないことがわかるので、たとえばput、URLにリクエストを送信すると、405で応答しますMethod Not Allowed

{
    "detail": "Method \"PUT\" not allowed."
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.