登录和我的个人资料 api 绑定在 django 模板中

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

这是我的登录 api 视图。我正在使用 adminlte 作为前端来开发管理面板

class LoginView(APIView):
       
    @extend_schema(request={'email', 'password'})
    def post(self, request):
        email = request.data.get('email')
        password = request.data.get('password')
        remember_me = request.data.get('remember_me')

        user = authenticate(email=email, password=password)

        if user:
            # Set the token expiration based on remember_me option
            if remember_me:
                token_lifetime = timezone.now() + timezone.timedelta(days=30)  # Long-lived token
            else:
                token_lifetime = timezone.now() + timezone.timedelta(minutes=24)  # Short-lived token

            # Generate or retrieve token for the authenticated user
            token, _ = Token.objects.get_or_create(user=user)
            token.created = timezone.now()
            token.expires = token_lifetime
            user.token =  token.key
            user.last_login = timezone.now()
            user.save(update_fields=['token', 'last_login'])
            token.save()

            return Response({ 'success': True, 'user_id': user.id, 'email': user.email, 'token': token.key}, status=status.HTTP_200_OK)
        else:
            return Response({ 'success': False, 'error': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)

这是我在 django 中的前端视图。

def login_view(request):

    if request.method == 'POST':
        data = {
            'email': request.POST['email'], 
            'password': request.POST['password']
        }

        csrf_token = request.COOKIES.get('csrftoken')
        headers = {'X-CSRFToken': csrf_token}

        response_content, status_code = Http.post(request, f"{settings.API_URL_V1}/login", data=data, headers=headers)

        if status_code == 200:
            token = response_content.get('token')
       
            if token:
                request.session['token'] = token
                messages.success(request, 'Logged in successfully')
                return redirect('dashboard')
        else:
            if not data['email'] and  not data['password']:
                messages.error(request, 'Email and Password cannot be Empty!')
            elif not 'password' or len('password') < 8 or not re.search("[!@#$%^&*()-_=+{};:,<.>]", 'password') or not re.search("[0-9]", 'password'):
                messages.error(request, 'Password must be at least 8 characters long and contain at least one special symbol and one number.')
    return render(request, 'login.html')

这是我的仪表板.html

{% extends 'adminlte/base.html' %}
{% block title %}Home{% endblock %}

{% block nav_header %}
{% include 'header.html' %}
{% endblock %}

{% block nav_sidebar %}
{% include 'sidebar.html' %}
{% endblock %}

{% block content %}
    Add content 
{% endblock %}

{% block nav_footer %}
{% include 'footer.html' %}
{% endblock %}

这是我的 header.html

{% block nav_header %}
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
    <ul class="navbar-nav">
        <li class="nav-item">
            <a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
        </li>
        <li class="nav-item d-none d-sm-inline-block">
            <a href="#" class="nav-link">About-us</a>
        </li>
        <li class="nav-item d-none d-sm-inline-block">
            <a href="#" class="nav-link">Contact-us</a>
        </li>
    </ul>

    <form class="form-inline ml-3">
        <div class="input-group input-group-sm">
            <input class="form-control form-control-navbar" type="search" placeholder="Search" aria-label="Search">
            <div class="input-group-append">
                <button class="btn btn-navbar" type="submit">
                    <i class="fas fa-search"></i>
                </button>
            </div>
        </div>
    </form>

    <ul class="navbar-nav ml-auto">
        <li class="nav-item dropdown">
            <a class="nav-link" data-toggle="dropdown" href="#">
                {% if data.profile_image %}
                    <img src="{{ data.profile_image }}" class="avatar img-circle" alt="My Profile">
                {% else %}
                    <i class="fas fa-user"></i>
                {% endif %}
            </a>
            <div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
                <div class="user-header bg-primary image">
                    {% if data.profile_image %}
                        <img src="{{ data.profile_image }}" class="img-circle" alt="{{ data.name }}">
                    {% else %}
                        <i class="fas fa-user-circle fa-5x"></i>
                    {% endif %}

                </div>

                <div class="dropdown-divider"></div>
                <a href="{% url 'my_profile' request.user.id %}" class="dropdown-item">
                    <i class="fas fa-lock mr-2"></i> My Profile
                </a>
                <a href="{% url 'reset_password' %}" class="dropdown-item">
                    <i class="fas fa-lock mr-2"></i> Change Password
                </a>
                <div class="dropdown-divider"></div>
                <a href="{% url 'signin' %}" class="dropdown-item dropdown-footer">Logout</a>
            </div>
        </li>
    </ul>
</nav>
{% endblock %}


在此,url

 <a href="{% url 'my_profile' request.user.id %}" class="dropdown-item"><i class="fas fa-lock mr-2"></i> My Profile</a>
为什么当用户登录成功时 request.user 返回匿名用户。我创建登录 api 是不是错了??

请建议如何获取用户和用户 ID,或建议另一种方法来执行此操作。

django django-rest-framework django-views django-templates drf-queryset
1个回答
0
投票

Django 的 request.user 不知道通过 API 完成的用户身份验证。 request.user 对象由 Django 的身份验证中间件使用 Django 的会话框架填充,该框架未在基于 API 的身份验证中使用。

在您的 API 中,您使用基于令牌的身份验证并在成功登录后将令牌存储在会话中。但是,Django 的身份验证中间件无法识别此令牌,并且 request.user 是匿名用户。

您可以使用 Django 的内置身份验证:如果您在管理面板中使用 Django 的模板和视图,则可以使用 Django 的内置身份验证系统,该系统与 request.user 配合良好。

或者编写一个自定义中间件来检查会话中的令牌,获取与令牌关联的用户,并设置 request.user。

from django.contrib.auth.middleware import MiddlewareMixin
from rest_framework.authtoken.models import Token

class TokenAuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        token_key = request.session.get('token')
        if token_key:
            try:
                token = Token.objects.get(key=token_key)
                request.user = token.user
            except Token.DoesNotExist:
                pass

将此中间件添加到 Django 设置文件中的 MIDDLEWARE 设置中。这只是一个简单的示例,可能无法涵盖所有情况。

© www.soinside.com 2019 - 2024. All rights reserved.