在DRF中如何从令牌字符串获取用户对象?

12
6个回答

35
from rest_framework.authtoken.models import Token
user = Token.objects.get(key='token string').user

如果你遇到了 AttributeError: type object 'Token' has no attribute 'objects' 错误, 那么请在 settings.py 文件中的 INSTALLED_APPS 部分中添加 "rest_framework.authtoken" - Abhishek Iyengar

7
如果您直接从 Token 类中调用用户对象,就像 @aliva 的解决方案中所演示的那样,您会得到仅包含数据库中字段的原始部分 Django 用户。如果您需要获取真实的用户对象,例如它的计算属性,您可以执行以下操作:
from rest_framework.authtoken.models import Token

user_id = Token.objects.get(key=request.auth.key).user_id
user = User.objects.get(id=user_id)

我收到 AttributeError: 'NoneType' 对象没有属性 'key' 的错误。 - nassim

3

以下是默认的授权令牌模型

@python_2_unicode_compatible
class Token(models.Model):
    """
    The default authorization token model.
    """
    key = models.CharField(_("Key"), max_length=40, primary_key=True)
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL, related_name='auth_token',
        on_delete=models.CASCADE, verbose_name=_("User")
    )
    created = models.DateTimeField(_("Created"), auto_now_add=True)

    class Meta:
        # Work around for a bug in Django:
        # https://code.djangoproject.com/ticket/19422
        #
        # Also see corresponding ticket:
        # https://github.com/encode/django-rest-framework/issues/705
        abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS
        verbose_name = _("Token")
        verbose_name_plural = _("Tokens")

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = self.generate_key()
        return super(Token, self).save(*args, **kwargs)

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

    def __str__(self):
        return self.key

您可以看到,这个模型与User模型具有一对一关系

所以如果您想获取映射到特定TokenUser

from rest_framework.authtoken.models import Token

try:
    Token.objects.get(key="token").user
except Token.DoesNotExist:
    pass

更多信息请参见认证文档


3
更好的方法是直接调用request.user,因为访问令牌表示经过身份验证的请求。DjangoRestFramework在成功的TokenAuthentication中提供对request.authrequest.user的访问。

2
假设您想在Django Rest Framework中获取认证令牌时获取userid和username。
更多信息可从https://www.django-rest-framework.org/api-guide/authentication/#by-exposing-an-api-endpoint获取。
# in views.py
from rest_framework.auth.models import Token
from rest_framework.auth.views import ObtainToken
from rest_framework.response import Response

class MyObtainToken(ObtainToken):
   """Return User Info along with token"""
   def post(self, request, *arg, **kwarg)
       serializer = self.serializer_class(request.data, context={'request':request})
       serializer.is_valid(raise_exception=True)
       user = serializer.valided_data['user']
       token, _ = Token.objects.get_or_create(user)
       return Response(
            {
                 'token': token.key,
                 'username': user.username,
                 'userid': user.pk
            })
# in urls.py
urlpatterns += [path(r'api/obtain_auth_token', MyObtainToken.as_view()]

除了一些打字错误外,建议的解决方案是可行的。 - acpmasquerade

0
你可以使用现有的ModelViewSet的@action来简化操作:
class UserViewSet(viewsets.ModelViewSet):
    ...
    @action(
        detail=False,
        methods=["get"],
        url_path=r"current",
    )
    def current_user(self, request):
        return Response(
            UserSerializer(request.user, context={"request": request}).data
        )

然后在以下位置获取:GET http://localhost:8000/yourapi/users/current/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接