24👍
The answer given by mariodev above is correct, as long as you’re only looking to make GET
requests.
If you want to POST
to a function you’re appending to a ViewSet, you need to use the action
decorator:
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...
Then you would POST
to a URL formatted like:
/myobjects/123/update_location/
http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing has more information if you’re interested!
15👍
You can now do this with the list_route and detail_route decorators: http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing
For example:
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)
- [Django]-ImportError: Couldn't import Django
- [Django]-Can I call a view from within another view?
- [Django]-How to select_related when using .get() in django?
8👍
You define method like you do now, but you need to use the same url as method name and add link decorator, so for
/myobjects/123/locations/
You add method like this
@link(permission_classes=[...])
def locations(self, request, pk=None):
...
and router will pick it automatically.
- [Django]-Django.db.utils.IntegrityError: duplicate key value violates unique constraint "django_content_type_pkey"
- [Django]-How to filter model results for multiple values for a many to many field in django
- [Django]-Multiple django sites with apache & mod_wsgi
3👍
From Routing to extra methods on a ViewSet:
I think you may need to route the method by hand, i.e. The Old-Fashioned Way™.
First pull the method out as a separate view:
set_password_view = UserViewSet.as_view({'post': 'set_password'})
(or such)
Then assign your URL:
url(r'^users/username_available/$', set_password_view, name-=...)
(Or such)
There’s a related question on SO.
- [Django]-How do I migrate a model out of one django app and into a new one?
- [Django]-Problems extend change_form.html in django admin
- [Django]-Docker – Can't access Django server
0👍
If you want to extend a viewset with a view that is or should not directly be written inside your viewset, you can write a “wrapper” action to pass the data through.
For example, with class based views:
from somewhere import YourExternalClassView
class SomeViewSet(viewsets.ReadOnlyModelViewSet):
# ...
@action(detail=True)
def your_action(self, request, pk):
return YourExternalClassView.as_view()(request, pk=pk)
How does it work?
On class based views, the as_view
method returns a view function, to which we will pass the data we received from the action. The view will then hand over to process further.
For non-class based view, the views can be called/wrapped directly without .as_view(...)(...)
.
- [Django]-Django gunicorn sock file not created by wsgi
- [Django]-Loop backwards using django template
- [Django]-Django: "No module named context_processors" error after reboot