Возможно иметь метод в APIView, вызываемый из url-адреса
в Django Rest Framework можно иметь пользовательский метод в APIView
класс можно назвать как .get()
или .post()
будет называться.
Я знаю, что это возможно с маршрутизаторами с использованием @action()
или @link()
декораторы, я пытаюсь выяснить, можете ли вы сделать что-то похожее на APIView
но имейте это, чтобы я мог установить метод на любой url, который я хочу.
Я пытался украсить класс с @action()
и @api_view()
но кажется, ничего работал.
Я не совсем уверен, что я должен поместить в URL-адрес конечной точки, чтобы фактически вызвать метод в классе. Буду ли я использовать CartAPIView.clear.as_view()
, CartAPIView.clear
или CartAPIView.clear()
. Я пробовал разные комбинации вызовов CartAPIView
но ничего не работает.
вот пример того, что я пытаюсь сделать:
# views.py
class CartAPIView(APIView):
@api_view(['POST'])
def clear(self, request):
"""Clear the users cart."""
queryset = Cart.objects.get(user=request.user)
queryset.clear_cart()
serializer = CartSerializer(queryset)
return Response(serializer.data, status=status.HTTP_200_OK)
# urls.py
urlpatterns = patterns('app.views',
....
url(r'^cart/clear/$', CartAPIView.clear.as_view(), name='clear_cart_api'),
....
)
любая помощь будет оценили.
3 ответов
вы, кажется, упускаете из виду, как работает поток представления на основе класса.
- как класс на основе класса (очевидно), и Django ожидает
несвязанная функция (не прикрепленная к классу или экземпляру) в виде представления,
as_view
обрабатывает это, создавая несвязанную функцию, и в этой функции создает экземпляр на основе класса вид. -
as_view
вызываетself.dispatch(request, *args, **kwargs)
, гдеself
- это только что созданный экземпляр объекта. -
dispatch
звонкиself.get(request, *args, **kwargs)
илиself.post(request, *args, **kwargs)
в зависимости от метода запроса (илиput
,patch
илиdelete
если это разрешено и используется).
там нет места для пользовательской функции, как ваш clear
функция, если вы не переопределите один из этих методов для вызова self.clear(request)
. Эквивалент @api_view(['POST'])
было бы переопределить post(request, *args, **kwargs)
способ:
# views.py
class CartAPIView(APIView):
def post(self, request, *args, **kwargs):
# Why would you call this 'queryset'? It's a single object.
cart = Cart.objects.get(user=request.user)
cart.clear_cart()
serializer = CartSerializer(cart)
return Response(serializer.data, status=status.HTTP_200_OK)
# urls.py
urlpatterns = patterns('app.views',
url(r'^cart/clear/$', CartAPIView.as_view(), name='clear_cart_api'),
)
Кажется, что вы ищете Представления На Основе Функций, где вы можете украсить функция с @api_view()
from rest_framework.decorators import api_view
@api_view(['POST'])
def clear(request):
"""Clear the users cart."""
queryset = Cart.objects.get(user=request.user)
queryset.clear_cart()
serializer = CartSerializer(queryset)
return Response(serializer.data, status=status.HTTP_200_OK)
# urls.py
urlpatterns = patterns('app.views',
....
url(r'^cart/clear/$', 'clear', name='clear_cart_api'),
....
)
оба ответа, опубликованные здесь @knbk и @almalki, являются действительными подходами к тому, что я спрашивал. Однако они не показывают, что я на самом деле сделал через несколько часов или около того.
Я закончил с помощью ViewSets, которые позволили мне связать GET
, POST
, etc запрашивает определенную функцию в классе ViewSet. Обычно вы используете маршрутизаторы для автоматической привязки всех соответствующих функций, но я хотел немного больше гибкости с тем, как они были связаны, так что я просто выписал их сам.
# views.py
class CartViewSet(ViewSet):
def clear(self, request):
"""Clear the users cart."""
queryset = Cart.objects.get(user=request.user)
queryset.clear_cart()
serializer = CartSerializer(queryset)
return Response(serializer.data, status=status.HTTP_200_OK)
clear_cart_viewset = CartViewSet.as_view({
'post': 'clear'
})
# urls.py
urlpatterns = patterns('app.views',
....
url(r'^cart/clear/$', 'clear_cart_viewset', name='clear_cart_api'),
....
)