Login_Required装饰器在Django中无法正常工作

时间:2020-09-20 09:06:48

标签: python django

我正在django建立一个网站。我使用了login_required装饰器来防止用户在没有成功登录的情况下移至UserView。但是我遇到的问题是,即使在成功进行登录身份验证之后,它也不会从登录页面移开并停留在登录页面上。我在做什么错了?

这是我的代码:

view.py

def LoginView(request):
    if request.method=='POST':
        username=request.POST.get('username')
        password=request.POST.get('password')
        try:
            user_info=User_Registration.objects.get(username=username)
           
            if user_info.password==password:
                return redirect("userview")
            else:

                   messages.info(request,"Invalid Password")
        except User_Registration.DoesNotExist:
            messages.info(request,"User Doesn't exist")
    else:

        return render(request,'login.html')

@login_required(login_url="login_view")
def UserView(request):
    return render(request,'user.html')

urls.py

from django.urls import path
from post_app import views

urlpatterns=[
    # path('',views.MainPageView.as_view()),
    path('/login',views.LoginView,name='login_view'),
    path('/userview',views.UserView,name='userview'),
    path('/registration',views.RegistrationView,name='registration_view'),
    path('new_job/<str:id>',views.post_new_job,name='new_job')
    
]

login.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'login.css' %}">
<!------ Include the above in your HEAD tag ---------->

<body>
    <div id="login">
        <h3 class="text-center text-white pt-5">Login form</h3>
        <div class="container">
            <div id="login-row" class="row justify-content-center align-items-center">
                <div id="login-column" class="col-md-6">
                    <div id="login-box" class="col-md-12">
                        <form id="login-form" class="form" action="" method="POST">
                            {% csrf_token %}
                            <h3 class="text-center text-info">Login</h3>
                            <div class="form-group">
                                <label for="username" class="text-info">Username:</label><br>
                                <input type="text" name="username" id="username" class="form-control">
                            </div>
                            <div class="form-group">
                                <label for="password" class="text-info">Password:</label><br>
                                <input type="password" name="password" id="password" class="form-control">
                            </div>
                            <div class="form-group">
                              
                                <input type="submit" name="submit" class="btn btn-info btn-md" value="submit">
                            </div>
                            <div id="register-link" class="text-right">
                                <a href="{% url 'registration_view' %}" class="text-info">Register here</a>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>


    <div>
        {% for message in messages %}
        <br>
        <h2  style="padding-left: 500px;" >{{message}}</h2>
        {% endfor %}
    </div>

</body>

</html>

5 个答案:

答案 0 :(得分:2)

您的代码未遵循在Django中实现身份验证/授权的最佳做法。无论如何,让我展示如何修复现有代码以使其正常工作。

def LoginView(request):
    if request.method=='POST':
        username=request.POST.get('username')
        password=request.POST.get('password')
        try:
            user_info=User_Registration.objects.get(username=username)
           
            if user_info.password==password:
                return redirect("userview")
            else:
                messages.info(request,"Invalid Password")
        except User_Registration.DoesNotExist:
            messages.info(request,"User Doesn't exist")
    return render(request,'login.html')

@login_required(login_url="login_view")
def UserView(request):
    return render(request,'user.html')

那怎么了?如果输入的用户不存在或密码无效-您什么也不做,只需添加一条错误消息。添加消息后,您应该呈现模板,并在其中迭代所有消息。 https://docs.djangoproject.com/en/3.1/ref/contrib/messages/#enabling-messages

上的更多信息

同时,这仍然无法按预期方式工作。我对您有一系列问题:

  1. 您是否以原始格式获得密码?我的意思是只包含密码的字符串,没有哈希和任何其他保护。
  2. 如何以User_Registration模式存储密码?还是密码字符串还是散列字符串?

在您的代码中,我还有一长串进一步的改进,但是让我们先找出错误。


更新(22.09.2020)

由于页面刷新后仍然停留在登录页面上-我认为未调用重定向代码。这意味着您应该看到添加的消息之一。请尝试在模板渲染期间将消息添加到上下文。让我们检查一下您将看到哪些消息。

def LoginView(request):
    if request.method=='POST':
        username=request.POST.get('username')
        password=request.POST.get('password')
        try:
            user_info=User_Registration.objects.get(username=username)
           
            if user_info.password==password:
                return redirect("userview")
            else:
                messages.info(request,"Invalid Password")
        except User_Registration.DoesNotExist:
            messages.info(request,"User Doesn't exist")
    return render(request,'login.html', {
        'messages': messages.get_messages(request)
    })

@login_required(login_url="login_view")
def UserView(request):
    return render(request,'user.html')

如果仍然没有收到任何消息,我们可以尝试将messages.info都替换为raise。因此,应用程序将在某处失败。但是,让我们尝试首先显式传递消息。

使邮件正常工作的清单https://docs.djangoproject.com/en/dev/ref/contrib/messages/#enabling-messages

  1. 'django.contrib.messages'在INSTALLED_APPS中
  2. MIDDLEWARE包含“ django.contrib.sessions.middleware.SessionMiddleware”和“ django.contrib.messages.middleware.MessageMiddleware”。
  3. 在TEMPLATES设置中定义的DjangoTemplates后端的'context_processors'选项包含'django.contrib.messages.context_processors.messages'

答案 1 :(得分:0)

views.py:

 @login_required
 def UserView(req):
     return render(req,"user.html")

setting.py:

LOGIN_URL = '/accounts/login/'  #Define your login page url..

答案 2 :(得分:0)

在您的views.py:

    if user_info.password == password: # I am not sure this is good way.
        return redirect("userview") # You cannot login here. If password equal password. This will redirect userview without login

请这样使用:

   from django.contrib.auth import login, authenticate # You need add this functions
   
   def LoginView(request):
       if request.method=='POST':
           username=request.POST.get('username')
           password=request.POST.get('password')
           user = authenticate(username=username, password=password) # You can control user with this function. If username and password are correct, this function will return this user. If incorrect, this will return None.
           if user is None:
                messages.info(request,"Username or password incorrect")
                return redirect("login_view")
           else:
               login(request, user) # You can login with this function
               messages.success(request, "You have successfully logged in")
               return redirect("userview")
        return render(request,'login.html')
    
    @login_required(login_url="login_view") # And now You can access this view. Because you logged in with login function
    def UserView(request):
        return render(request,'user.html')

我的英语水平不好,但是我试图解释。

答案 3 :(得分:0)

Redirct方法接受3种类型的参数;

  1. 模型:将调用模型的get_absolute_url()函数。
  2. 视图名称,可能带有参数:reverse()将用于反向解析 名字。
  3. 绝对或相对URL,将按原样用作重定向位置。

确保使用正确的视图名称。

答案 4 :(得分:0)

研究了类似问题后,您可以尝试:

  • 从浏览器中删除缓存。

此外,由于该网站的登录网址为静态。您可以在login_url中定义settings.py,例如:

LOGIN_URL = '/post_app/login'

然后,您不必在使用 login_url 的任何地方定义它。否则,一切看起来都很好。