viewset - partial update django rest framework
Agregar más vistas a un enrutador o conjunto de vistas(Django-Rest-Framework) (4)
Ahora puede hacer esto con los decoradores list_route y detail_route: http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing
Por ejemplo:
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)
Esencialmente, estoy tratando de encontrar una buena manera de adjuntar más vistas a un enrutador sin crear un enrutador personalizado. ¿Cuál es una buena manera de lograr esto?
Aquí hay algo parecido a lo que estoy tratando de lograr. Se han cambiado los nombres de las variables y el método de ejemplo que quiero introducir está extremadamente simplificado por el bien de esta pregunta.
Enrutador
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()
Un ejemplo de otro tipo de método que necesito incluir. (Hay muchos de estos):
def get_locations(self, request):
""" Returns a list of location objects somehow related to MyObject """
locations = calculate_something()
return Response(locations)
El resultado final es que la siguiente URL funcionaría correctamente y se implementaría "limpiamente".
GET example.com/myobjects/123/locations
Del enrutamiento a métodos adicionales en un ViewSet :
Creo que es posible que deba enrutar el método a mano, es decir, The Old-Fashioned Way ™.
Primero saca el método como una vista separada:
set_password_view = UserViewSet.as_view({''post'': ''set_password''})
(o tal)
Luego asigne su URL:
url(r''^users/username_available/$'', set_password_view, name-=...)
(O tal)
Hay una pregunta relacionada en SO .
La respuesta dada por mariodev arriba es correcta, siempre y cuando solo esté buscando realizar solicitudes GET
.
Si desea POST
a una función que está agregando a un ViewSet, necesita usar el decorador de 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...
Luego, /myobjects/123/update_location/
un POST
a una URL con formato como: /myobjects/123/update_location/
http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing tiene más información si está interesado.
Usted define el método como lo hace ahora, pero necesita usar la misma url como nombre del método y agregar el decorador de enlaces, así que para
/myobjects/123/locations/
Usted agrega método como este
@link(permission_classes=[...])
def locations(self, request, pk=None):
...
y el enrutador lo recogerá automáticamente.