在 django 中间件中访问登录用户名

问题描述 投票:0回答:0

我正在尝试访问以下 django 中间件中的

request.user.username

class MyMiddleware():
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        user_id = request.user.username
        # ... 

我确保

MyMiddleware
出现在
SessionMiddleware
AuthenticationMiddleware
之后
settngs.py

MIDDLEWARE = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # ...
    `my_app.my_py_file.MyMiddleware`
)

request.user.username
仍然是一个空字符串。

Q1.为什么会这样?

我也试过添加

@authentication_classes([TokenAuthentication,])

from rest_framework.authentication import TokenAuthentication # <--
from rest_framework.decorators import authentication_classes # <--

@authentication_classes([TokenAuthentication,]) # <--
class MyMiddleware():
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        user_id = request.user.username
        # ... 

但没有帮助。

我也尝试制作类

APIView
(虽然它看起来很愚蠢,因为中间件不是 REST API):

from rest_framework.authentication import TokenAuthentication # <--
from rest_framework.views import APIView # <--

class MyMiddleware(APIView): # <-- 
    authentication_classes = [TokenAuthentication] # <--
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        user_id = request.user.username
        # ... 

仍然没有用。

然后我遇到了这个答案。它说:

如果使用 simple_jwt,则无法在中间件中直接使用 request.user,因为身份验证机制在视图函数中起作用。因此,您应该在中间件内部手动进行身份验证,然后您可以使用 request.user 从用户模型中获取任何数据。

它使用

rest_framework_simplejwt
,它似乎不是django框架的一部分,需要明确安装。

我能够在我的中间件中访问

username
的唯一方法是使用this answer。我修改了我的中间件如下:

from re import sub
from rest_framework.authtoken.models import Token

class MyMiddleware(object):

    def __init__(self, get_response):
        self.get_response = get_response


    def __call__(self, request):
        response = self.get_response(request)
        user_id = request.user.username

        if not user_id: 
            user_id = self.getUsername(request)
        
        # ...
    
    def getUsername(self, request):
        header_token = request.META.get('HTTP_AUTHORIZATION', None)
        if header_token is not None:
            try:
                token = sub('Token ', '', header_token)
                token_obj = Token.objects.get(key = token)
            except Token.DoesNotExist:
                pass
        return token_obj.user.username

Q2. 这是在不安装第三方库的情况下访问中间件内部用户名的唯一且正确的方法吗?

更新

下面是我的

CustomUser
课程和可能相关的方法
create_custom_user()

class CustomUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # there are some application specific fields    

@receiver(post_save, sender=User)
@debugger_queries
def create_custom_user(sender, **kwargs):
    instance = kwargs['instance']
    if kwargs['created']:  # create
        CustomUser.objects.get_or_create(user=instance)
python django django-rest-framework django-views django-middleware
© www.soinside.com 2019 - 2024. All rights reserved.