Подтвердить что ты не робот

Добавление большего количества просмотров в Router или viewet (Django-Rest-Framework)

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

Вот что-то вроде того, что я пытаюсь выполнить. Имена переменных были изменены, и примерный метод, который я хочу ввести, чрезвычайно упрощен ради этого вопроса.

Router:

router = routers.SimpleRouter(trailing_slash=False)
router.register(r'myobjects', MyObjectViewSet, base_name='myobjects')
urlpatterns = router.urls

Viewset

class MyObjectsViewSet(viewsets.ViewSet):
""" Provides API Methods to manage MyObjects. """

def list(self, request):
    """ Returns a list of MyObjects. """
    data = get_list_of_myobjects()
    return Response(data)

def retrieve(self, request, pk):
    """ Returns a single MyObject. """
    data = fetch_my_object(pk)
    return Response(data)

def destroy(self, request, pk):
    """ Deletes a single MyObject. """
    fetch_my_object_and_delete(pk)
            return Response()

Один пример другого типа метода, который мне нужно включить. (Их много):

def get_locations(self, request):
    """ Returns a list of location objects somehow related to MyObject """
    locations = calculate_something()
    return Response(locations)

Конечным результатом является то, что следующий URL-адрес будет работать корректно и будет реализован "чисто".

GET example.com/myobjects/123/locations
4b9b3361

Ответ 1

ответ, приведенный mariodev выше, верен, если вы только хотите сделать запросы GET.

Если вы хотите использовать POST для функции, которую вы добавляете в ViewSet, вам нужно использовать декоратор action:

from rest_framework.decorators import action, link
from rest_framework.response import Response

class MyObjectsViewSet(viewsets.ViewSet):

    # For GET Requests
    @link()
    def get_locations(self, request):
        """ Returns a list of location objects somehow related to MyObject """
        locations = calculate_something()
        return Response(locations)

    # For POST Requests
    @action()
    def update_location(self, request, pk):
        """ Updates the object identified by the pk """
        location = self.get_object()
        location.field = update_location_field() # your custom code
        location.save()

        # ...create a serializer and return with updated data...

Затем вы должны были бы POST отформатировать URL как: /myobjects/123/update_location/

http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing имеет больше информации, если вам интересно!

Ответ 2

Теперь вы можете сделать это с помощью декораторов list_route и detail_route: http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing

Например:

from rest_framework.decorators import list_route
from rest_framework.response import Response
...

class MyObjectsViewSet(viewsets.ViewSet):
    ...

    @list_route()
    def locations(self, request):
        queryset = get_locations()
        serializer = LocationSerializer(queryset, many=True)
        return Response(serializer.data)

Ответ 3

Вы определяете метод, как сейчас, но вам нужно использовать тот же URL-адрес, что и имя метода, и добавить декоратор ссылок, поэтому для

/myobjects/123/locations/

Вы добавляете метод, подобный этому

@link(permission_classes=[...])
def locations(self, request, pk=None):
    ...

и маршрутизатор автоматически выбирает его.

Ответ 4

От Маршрутизация дополнительных методов в ViewSet:

Думаю, вам, возможно, понадобится направить метод вручную, т.е. Old-Fashioned Way ™.

Сначала вытащите метод как отдельный вид:

   set_password_view = UserViewSet.as_view({'post': 'set_password'})

(или такой)

Затем назначьте свой URL-адрес:

   url(r'^users/username_available/$', set_password_view, name-=...)

(Или такой)

Здесь связанный вопрос на SO.