在Django Rest Framework中使用Tokenauthentication进行身份验证时,不会更新last_login字段

F.D*_*.F. 14 python django rest login django-rest-framework

我正在一个项目中工作,该项目依赖于Django用户模型和DjangoRestFramework下的TokenAuthentication

我被要求为每个用户获取最后一次登录日期时间,并且我已经意识到当我调用身份验证REST端点时,该字段没有得到更新.

这是一个已知的事实吗?为了在每次调用令牌认证时更新该字段,我是否遗漏了必须执行的操作?

谢谢

F.D*_*.F. 10

好吧,最后我从REST Framework TokenAuthentication继承,在urls文件中指向它

url(r'^api-token-auth/', back_views.TokenAuthenticationView.as_view()),
Run Code Online (Sandbox Code Playgroud)

并且View处理请求并手动调用update_last_login,如下所示:

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
Run Code Online (Sandbox Code Playgroud)


Fai*_*mad 8

如果您使用 Simple JWT for Django,则可以通过以下链接轻松完成此操作。你只需要添加

SIMPLE_JWT = {
...,
'UPDATE_LAST_LOGIN': True,
...,
}
Run Code Online (Sandbox Code Playgroud)


Cha*_*thk 6

@FDF的答案很好。这是另一种方法。

我们发送以下user_logged_in信号update_last_login

user_logged_in.send(sender=user.__class__, request=request, user=user)

这是一个工作视图(基于使用电子邮件作为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()
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到完整的源代码:更新了last_login的Api视图

希望这可以帮助。

  • 这在某种程度上*感觉*像是一种更好的方法——你知道有什么具体的优点/缺点吗? (2认同)

Gut*_*gao 5

一种更清洁的方法:

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
Run Code Online (Sandbox Code Playgroud)

然后设置 urls.py:

url(r'^api-token-auth/', views.LoginToken.as_view()),
Run Code Online (Sandbox Code Playgroud)