Deaktivieren Sie eine Methode in einem ViewSet, Django-Rest-Framework


123

ViewSets über automatische Methoden zum Auflisten, Abrufen, Erstellen, Aktualisieren, Löschen, ...

Ich möchte einige davon deaktivieren, und die Lösung, die ich gefunden habe, ist wahrscheinlich keine gute, da diese OPTIONSimmer noch als zulässig angegeben werden.

Irgendeine Idee, wie man das richtig macht?

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)

Antworten:


249

Die Definition von ModelViewSetist:

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

ModelViewSetWarum also nicht einfach alles verwenden, was Sie brauchen, anstatt es zu erweitern ? Also zum Beispiel:

from rest_framework import viewsets, mixins

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

Bei diesem Ansatz sollte der Router nur Routen für die enthaltenen Methoden generieren.

Referenz :

ModelViewSet


@SunnySydeUp Versuchen Sie es jetzt und es scheint, dass der Router die Route für eine Listenansicht generiert, aber es ist 404s, weil das ViewSet nicht weiß, wie die Anfrage zu behandeln ist. Hast du das erwartet?
Steve Jalim

3
Wenn Sie nur die benötigten Mixins verwenden, können Sie die Methoden GET, POST, PUT, DELETE deaktivieren. Ich konnte jedoch nicht herausfinden, wie die PATCH-Methode deaktiviert werden kann, insbesondere wenn Sie Router verwenden.
Muneeb Ahmad

3
@MuneebAhmad Die PATCH-Methode wird von der aktiviert UpdateModelMixin. Wenn Sie das Update verwenden möchten, aber nicht den Patch, kann ich mir derzeit zwei Möglichkeiten vorstellen. Sie können entweder die zulässigen Methoden in der Ansicht überschreiben und "Patch" entfernen oder die partial_updateMethode und den Aufruf überschreiben http_method_not_allowed(request, *args, **kwargs). Ich habe dies nicht getestet, daher bin ich mir nicht sicher, ob es funktioniert
SunnySydeUp

1
@ JulioMarins Ich habe eine Referenz hinzugefügt. Ich bin mir nicht sicher, ob Sie das wollten.
SunnySydeUp

1
Wenn jemand ein schreibgeschütztes Viewset erstellen möchte, kann er es verwenden class SampleViewSet(viewsets.ReadOnlyModelViewSet).
Bikash kharel

131

Sie können Ihr ViewSet weiterhin verwenden viewsets.ModelViewSetund definieren http_method_names.

Beispiel

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

Sobald Sie hinzufügen http_method_names, werden Sie nicht mehr in der Lage sein putund patch.

Wenn Sie wollen, putaber nicht wollen patch, können Sie behaltenhttp_method_names = ['get', 'post', 'head', 'put']

Intern erstrecken sich DRF-Ansichten von Django CBV. Django CBV hat ein Attribut namens http_method_names. Sie können also auch http_method_names mit DRF-Ansichten verwenden.

[Shameless Plug]: Wenn diese Antwort hilfreich war, wird Ihnen meine Reihe von Beiträgen zu DRF unter https://www.agiliq.com/blog/2019/04/drf-polls/ gefallen .


16
Das Problem auf diese Weise besteht nicht darin, die Liste zu deaktivieren oder abzurufen.
Fuad

1
Dies funktionierte nicht für mich, nachdem ich get und head eingeschlossen hatte, konnte ich immer noch einen Beitrag
schreiben

Dies funktioniert bei mir auf Django 1.9. Tolle Lösung. Gibt es ein Risiko, dass Benutzer eine GET-Anfrage auf andere Weise ausführen können?
Ycon

FANTASTISCHE Lösung. Funktioniert python3und Django 1.10gut.
Urda

2
Ich bevorzuge diesen Ansatz, weil ich die Vererbung von Mixins nicht ändern konnte, um PATCH einzuschließen, aber nicht PUT, weil beide eine Implementierung von mixins.UpdateModelMixin
ThatsAMorais

5

Obwohl es eine Weile her ist, dass dieser Beitrag veröffentlicht wurde, habe ich plötzlich herausgefunden, dass es tatsächlich eine Möglichkeit gibt, diese Funktion zu deaktivieren. Sie können sie direkt in views.py bearbeiten.

Quelle: 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)

Dies sollte ein bevorzugter Weg sein.
Digitake

Ich denke, HTTP_400_BAD_REQUEST wäre hier besser geeignet, wenn es nicht mit auth zusammenhängt.
Santiago Magariños

4

Wenn Sie versuchen, die PUT-Methode in einem DRF-Ansichtssatz zu deaktivieren, können Sie einen benutzerdefinierten Router erstellen:

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

Wenn Sie die Methode am Router deaktivieren, ist die Dokumentation Ihres API-Schemas korrekt.


Da ein Teil-Patch in DRF nicht korrekt implementiert ist, ist es ratsam, ihn global auf die hier beschriebene Weise zu entfernen
oden

1

So deaktivieren Sie die Methode "DELETE" für ViewSet in DRF

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

PS Dies ist zuverlässiger als die explizite Angabe aller erforderlichen Methoden, sodass die Wahrscheinlichkeit geringer ist, dass einige wichtige Methoden vergessen werden. OPTIONEN, KOPF usw.

PPS hat standardmäßig DRF http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']


Sie können nicht superauf Klassenebene anrufen , es gibt keine self.
Gültiger Name

0

In Django Rest Framework 3.xx können Sie einfach jede Methode aktivieren, für die Sie aktiviert werden möchten ModelViewSet, indem Sie ein Wörterbuch an die as_viewMethode übergeben. In diesem Wörterbuch muss der Schlüssel den Anforderungstyp (GET, POST, DELETE usw.) und der Wert den entsprechenden Methodennamen (Liste, Abrufen, Aktualisieren usw.) enthalten. Angenommen, Sie möchten, dass ein SampleModell erstellt oder gelesen wird, aber nicht, dass es geändert wird. Also es heißt , Sie wollen list, retrieveund createVerfahren zu ermöglichen (und Sie andere wollen deaktiviert sein.)

Alles, was Sie tun müssen, ist, Pfade hinzuzufügen, um urlpatternsdiese zu mögen:

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

Wie Sie sehen können, gibt es in den obigen Routing-Einstellungen keine deleteund keine putAnfrage. Wenn Sie beispielsweise eine putAnfrage an die URL senden , erhalten Sie eine Antwort mit 405 Method Not Allowed:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.