last_login field is not updated when authenticating using Tokenauthentication in Django Rest Framework
Well, at the end I inherited from the REST Framework TokenAuthentication, pointing to it in the urls file
url(r'^api-token-auth/', back_views.TokenAuthenticationView.as_view()),
and the View handles the request and manually calls the update_last_login like this:
from django.contrib.auth.models import update_last_login
class TokenAuthenticationView(ObtainAuthToken):
"""Implementation of ObtainAuthToken with last_login update"""
def post(self, request):
result = super(TokenAuthenticationView, self).post(request)
try:
request_user, data = requests.get_parameters(request)
user = requests.get_user_by_username(data['username'])
update_last_login(None, user)
except Exception as exc:
return None
return result
@F.D.F. answer is great. Here is another way of doing it.
We send user_logged_in
signals that will call update_last_login
:
user_logged_in.send(sender=user.__class__, request=request, user=user)
Here is a working view (based on a custom User model that uses email as USERNAME_FIELD) :
from rest_framework import parsers, renderers
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.auth.signals import user_logged_in
from emailauth.serializers import AuthTokenSerializer, UserSerializer
class ObtainAuthToken(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
user_logged_in.send(sender=user.__class__, request=request, user=user)
return Response({'token': token.key, 'user': UserSerializer(user).data})
obtain_auth_token = ObtainAuthToken.as_view()
You can find the full source code here : Api View with last_login updated
Hope this helps.
A cleaner way to do it:
from django.contrib.auth.models import update_last_login
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken
class LoginToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
result = super().post(request, *args, **kwargs)
token = Token.objects.get(key=result.data['token'])
update_last_login(None, token.user)
return result
And then setup urls.py:
url(r'^api-token-auth/', views.LoginToken.as_view()),