Django-rest-framework: Can API api-token-auth return user id

Created on 14 Jan 2015  路  8Comments  路  Source: encode/django-rest-framework

When user login from client (visit api-token-auth and get the token), return just token, without user id,
So I have to get user info again, I think may return id and token is more useful.

Most helpful comment

@ctippur: A slightly more expanded-upon example below, for including the user's id in the response payload ---

# myapp/views.py
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response


class CustomObtainAuthToken(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        response = super(CustomObtainAuthToken, self).post(request, *args, **kwargs)
        token = Token.objects.get(key=response.data['token'])
        return Response({'token': token.key, 'id': token.user_id})
# myapp/urls.py
from django.conf.urls import url

from .views import CustomObtainAuthToken

urlpatterns = [
    url(r'^authenticate/', CustomObtainAuthToken.as_view()),
]
# Sample results
$ http :8000/authenticate/ username=someuser password=secretpassword
HTTP/1.0 200 OK
Allow: POST, OPTIONS
Content-Language: en
Content-Type: application/json
Date: Tue, 22 Mar 2016 18:30:10 GMT
Server: WSGIServer/0.2 CPython/3.5.1
Vary: Accept-Language, Cookie
X-Frame-Options: SAMEORIGIN

{
    "id": 16, 
    "token": "82e0bc9980a6b2c9a70969b0f8dc974418dda399"
}

As @carltongibson mentioned, the idea here is to overide the post method of the ObtainAuthToken view class. Here all I have done is call the parent class to get the token, then look up that token to find the associated user id. Hope that helps.

All 8 comments

The view here is _quite simple_. You're welcome to override rest_framework.authtoken.views.ObtainAuthToken.post in order to get the result you want.

If you're heading this route returning a full user profile, in addition to your token, may be useful.

return Response({
   'token': token.key
   'user' : MyUserSerializer(user).data
})

...or such.

Can you please elaborate on this solution?

@ctippur: A slightly more expanded-upon example below, for including the user's id in the response payload ---

# myapp/views.py
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response


class CustomObtainAuthToken(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        response = super(CustomObtainAuthToken, self).post(request, *args, **kwargs)
        token = Token.objects.get(key=response.data['token'])
        return Response({'token': token.key, 'id': token.user_id})
# myapp/urls.py
from django.conf.urls import url

from .views import CustomObtainAuthToken

urlpatterns = [
    url(r'^authenticate/', CustomObtainAuthToken.as_view()),
]
# Sample results
$ http :8000/authenticate/ username=someuser password=secretpassword
HTTP/1.0 200 OK
Allow: POST, OPTIONS
Content-Language: en
Content-Type: application/json
Date: Tue, 22 Mar 2016 18:30:10 GMT
Server: WSGIServer/0.2 CPython/3.5.1
Vary: Accept-Language, Cookie
X-Frame-Options: SAMEORIGIN

{
    "id": 16, 
    "token": "82e0bc9980a6b2c9a70969b0f8dc974418dda399"
}

As @carltongibson mentioned, the idea here is to overide the post method of the ObtainAuthToken view class. Here all I have done is call the parent class to get the token, then look up that token to find the associated user id. Hope that helps.

@thermokarst .... Thank you for that! I had the same problem here!

Thank you, but tried this and keep getting this {"detail":"Method \"GET\" not allowed."} in browser...please help

@PamilerinId The view is POST only, hence the error. Make a POST request instead of a GET. (The discussion group is the best place to take usage questions. Thanks!)

This is my users/urls.py

from rest_framework.routers import DefaultRouter
from . import views as user_views
from django.conf.urls import url ,include
from .views import CustomObtainAuthToken

router = DefaultRouter()
router.register(r'user', user_views.UserViewSet,base_name="user")

urlpatterns = [
url(r'^authenticate/', user_views.CustomObtainAuthToken),
]
urlpatterns = router.urls

This is users/view.py

class CustomObtainAuthToken(ObtainAuthToken):
def post(self, request, args, *kwargs):
response = super(CustomObtainAuthToken, self).post(request, args, *kwargs)
token = Token.objects.get(key=response.data['token'])
return Response({'token': token.key, 'id': token.user_id})

This is projectrooot/urls.py

from django.contrib import admin
from django.conf.urls import url ,include
from rest_framework.authtoken import views

urlpatterns = [
url(r'', include('users.urls')),
url(r'^api-token-auth/', views.obtain_auth_token),
url(r'^admin/', admin.site.urls),
]

When I hit http://127.0.0.1:8000/authenticate/ from rest client my terminal says Not Found: /authenticate/ . Is my urls.py files mapping correct ?Please help?

urlpatterns = router.urls

You overwrote your authenticate/ declaration. (You probably wanted +=.)

The discussion group is the best place to take usage questions. Please don't ask support questions on the issue tracker. Thanks!

Was this page helpful?
0 / 5 - 0 ratings