Добавление большего количества просмотров в 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
Ответы
Ответ 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.