Django-Rest-Framework: Могу ли я создать viewset с двумя разными методами с одинаковым url_path, но разными методами запроса? - PullRequest
0 голосов
/ 21 декабря 2018

Вот набор параметров

class MobileDeviceViewset(ModelViewSet):
    @action(
        methods=['post', 'put', 'patch'],
        url_path='token',
        detail=True,
    )
    def update_token(self, request, *args, **kwargs) -> Response:
        ...

    @action(
        methods=['get'],
        url_path='token',
        detail=True,
    )
    def get_token(self, request, *args, **kwargs) -> Response:
        ...

Так что я хочу сделать здесь иметь конечную точку /token/, на которую приложение отправит запрос GET, чтобы проверить, есть ли токен, и получить его, еслиесть.Я также хочу использовать ту же конечную точку /token/ для отправки обновленного токена.В настоящее время происходит то, что я получаю сообщение об ошибке, сообщающее, что методы POST / PATCH / PUT не разрешены на этой конечной точке, поэтому он, похоже, распознает только метод get_token.Объект токена на самом деле является моделью ManyToMany через MobileDeviceUser, поэтому я не просто пытаюсь обновить поле в объекте MobileDevice.

1 Ответ

0 голосов
/ 21 декабря 2018

Поскольку ваши url_path и detail одинаковы в обоих случаях, зачем вам два разных метода в ваших представлениях ??
В любом случае, я бы порекомендовал этот способ,

class MobileDeviceViewset(ModelViewSet):
    # your code

    <b>@action(methods=['get', 'post', 'put', 'patch'], url_path='token', detail=True, )
    def my_action(self, request, *args, **kwargs):
        if request.method == 'GET':
            return self.get_token(request, *args, **kwargs)
        else:
            return self.update_token(request, *args, **kwargs)</b>

    def update_token(self, request, *args, **kwargs):
        return Response("update token response--{}".format(request.method))

    def get_token(self, request, *args, **kwargs):
        return Response("update token response--{}".format(request.method))

Затем вам нужно внести некоторые изменения в конфигурацию вашего URL,

from django.urls import path
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
<b>router.register('mysample', MobileDeviceViewset, base_name='mobile-device')
actions = {
    "get": "my_action",
    "post": "my_action",
    "put": "my_action",
    "patch": "my_action"
}
urlpatterns = [
                  path('mysample/&ltpk>/token/', MobileDeviceViewset.as_view(actions=actions))

              ] + router.urls</b>

Следовательно, ваш URL будет выглядеть примерно так: ..../mysample/3/token/

ПРИМЕЧАНИЕ
Это решение протестировано под Python 3.6, Django==2.1 и DRF==3.8.2


ОБНОВЛЕНИЕ

Почему Method Not Allowed ошибка?

Когда в Django приходит запрос, он ищет шаблоны в конфигах URL и отправляет запрос в соответствующее представление в случае совпадения.
В вашем случае вы определили два представления (да .. хотя это действия) с одним и тем же URL (как показано ниже).

actions = {
    "post": "update_token",
    "put": "update_token",
    "patch": "update_token"
}

urlpatterns = [
                  path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions={"get": "get_token"})),
                  path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions=actions))

              ] + router.urls


В этом случае приходит запрос (пустьэто будет HTTP POST ), и диспетчер URL перенаправляет в первое представление , которое удовлетворяет пути URL.Итак, запрос POST входит в метод get_token, но он разрешен только для метода GET


Что такоевозможное решение?

Метод-1:
Как я уже говорил выше, используйте общее действие и distingush для HTTP METHODS и вызывайте соответствующие методы
Метод 2:
Использовать разные пути URL для обоих действий, например

actions = {
    "post": "my_action",
    "put": "my_action",
    "patch": "my_action"
}
urlpatterns = [
                  path('mysample/<pk>/get-token/', MobileDeviceViewset.as_view(actions={"get": "get_token"})),
                  path('mysample/<pk>/update-token/', MobileDeviceViewset.as_view(actions=actions))

              ] + router.urls
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...