3👍
Since your url_path
and detail
are the same in both cases, why do you want two separate methods in your views??
Anyway I would recommend this way,
class MobileDeviceViewset(ModelViewSet):
# your code
@action(methods=['get', 'post', 'put', 'patch'], url_path='token', detail=True, )
def my_action(self, request, *args, **kwargs):
if request.method == 'GET':
return self.get_token(request, *args, **kwargs)
else:
return self.update_token(request, *args, **kwargs)
def update_token(self, request, *args, **kwargs):
return Response("update token response--{}".format(request.method))
def get_token(self, request, *args, **kwargs):
return Response("update token response--{}".format(request.method))
Then you have to make some changes in your URL config,
from django.urls import path
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('mysample', MobileDeviceViewset, base_name='mobile-device')
actions = {
"get": "my_action",
"post": "my_action",
"put": "my_action",
"patch": "my_action"
}
urlpatterns = [
path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions=actions))
] + router.urls
Hence, your URL will some something like, ..../mysample/3/token/
NOTE
This solution tested under Python 3.6
, Django==2.1
and DRF==3.8.2
UPDATE
Why Method Not Allowed
error?
When a request comes to Django, it searches for the patterns in the URL configs and sends the request to the corresponding view if a match occurs.
In your case, you’ve defined two views (yes..it’s actions though) with the same URL (as below,).
actions = {
"post": "update_token",
"put": "update_token",
"patch": "update_token"
}
urlpatterns = [
path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions={"get": "get_token"})),
path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions=actions))
] + router.urls
In this case, a request comes (let it be a HTTP POST) and the URL dispatcher redirects to the first view which satisfies the URL path. So, the POST request goes into the get_token
method, but, it’s only allowed for GET method
What is the possible solution?
Method-1:
As I described in the top, use a common action and distingush the HTTP METHODS and call appropriate methods
Method-2:
Use different URL path for both actions, as
actions = {
"post": "my_action",
"put": "my_action",
"patch": "my_action"
}
urlpatterns = [
path('mysample/<pk>/get-token/', MobileDeviceViewset.as_view(actions={"get": "get_token"})),
path('mysample/<pk>/update-token/', MobileDeviceViewset.as_view(actions=actions))
] + router.urls
3👍
you can do this via:
class MobileDeviceViewset(ModelViewSet):
@action(
methods=['get'],
url_path='token',
url_name='token',
detail=True,
)
def get_token(self, request, *args, **kwargs) -> Response:
...
@get_token.mapping.post
@get_token.mapping.put
@get_token.mapping.patch
def update_token(self, request, *args, **kwargs) -> Response:
...
- [Django]-How to add Redis Database in Django-1.9?
- [Django]-Docker-compose ERROR [internal] booting buildkit, http: invalid Host header while deploy Django
- [Django]-Upload directly to S3 from django
- [Django]-Editing models and extending database structure in Saleor
- [Django]-Django handle Annonymous users