Вимкніть метод у ViewSet, django-rest-frame


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 Просто спробувавши це зараз, і, здається, маршрутизатор генерує маршрут для перегляду списку, але це 404s, оскільки ViewSet не знає, як обробляти запит. Це те, чого ви очікували?
Стів Джалім

3
Використовуючи лише потрібні мікси, ви можете вимкнути методи GET, POST, PUT, DELETE, але я не зміг дізнатися, як відключити метод PATCH спеціально, якщо ви використовуєте маршрутизатори.
Muneeb Ahmad

3
@MuneebAhmad Метод PATCH увімкнено з UpdateModelMixin. Якщо ви хочете використовувати оновлення, але не патч, я зараз можу придумати два способи. Ви можете або замінити дозволені методи у вікні перегляду та видалити "виправлення", або ви можете перекрити partial_updateметод та викликати http_method_not_allowed(request, *args, **kwargs). Я цього не перевіряв, тому не впевнений, чи працює він
SunnySydeUp

1
@JulioMarins Я додав посилання. Я не впевнений, чи це ви хотіли.
SunnySydeUp

1
Якщо хтось хоче зробити набір перегляду лише для читання, він може використовувати його class SampleViewSet(viewsets.ReadOnlyModelViewSet).
Бікаш-харел

133

Ви можете продовжувати використовувати viewsets.ModelViewSetта визначати http_method_namesу своєму ViewSet.

Приклад

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

Як тільки ви додасте http_method_names, ви більше не зможете це зробити putі patchбільше.

Якщо ви хочете, putале не хочете patch, можете триматиhttp_method_names = ['get', 'post', 'head', 'put']

Внутрішнє враження від DRF поширюється на CBD Django. Django CBV має атрибут під назвою http_method_names. Таким чином, ви можете використовувати http_method_names і для перегляду DRF.

[Безсоромний штекер]: Якщо ця відповідь була корисною, вам сподобається моя серія публікацій на DRF за адресою https://www.agiliq.com/blog/2019/04/drf-polls/ .


16
Проблема з цим способом полягає не в тому, щоб відключити список або отримати його. Доведено відключити і те, і інше
Fuad

1
Це не спрацювало для мене, після включення get and head я все-таки змогла зробити пост
RunLoop

Це працює для мене на django 1.9. Прекрасне рішення. Чи існує ризик, що користувачі можуть зробити запит GET іншим способом?
Ycon

FANTASTIC розчин. Працює python3і Django 1.10просто чудово.
Урда

2
Я віддаю перевагу такому підходу, тому що я не зміг змінити спадщину міксинів на включення PATCH, але не PUT, оскільки вони обидва є реалізацією mixins.UpdateModelMixin
ThatsAMorais

5

Хоча минув час на цій посаді, я раптом з’ясував, що насправді це спосіб відключити ці функції, ви можете редагувати її в views.py безпосередньо.

Джерело: https://www.django-rest-framework.org/api-guide/viewsets/#viewset-action

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)

Це має бути бажаним способом.
digitake

Я думаю, що HTTP_400_BAD_REQUEST було б більш доречним тут, якщо він не пов'язаний з auth.
Сантьяго Магаріньос

4

Якщо ви намагаєтесь відключити метод PUT з набору перегляду DRF, ви можете створити власний маршрутизатор:

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

Як відключити метод "DELETE" для ViewSet в 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 Це надійніше, ніж чітко вказати всі необхідні методи, тому менше шансів забути деякі важливі методи ВАРІАНТИ, ГОЛОВА тощо

PPS за замовчуванням має DRF 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створити або прочитати модель, але ви не хочете, щоб її змінювали. Так це означає, що ви хочете list, retrieveі createметод потрібно включити (і ви хочете, щоб інші були відключені.)

Все, що вам потрібно зробити, - це додати шляхи до urlpatternsтаких:

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

Як ви можете бачити , немає ніякого deleteі putзапиту в налаштуваннях вище маршрутизації, наприклад , якщо ви відправляєте putзапит на URL - адреса, то відповідь ви з 405 Method Not Allowed:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.