Django自定义客户端登录页面未进行身份验证

时间:2017-01-10 22:49:46

标签: python django authentication

Django的新手来自Laravel,在那里设置登录和身份验证要容易得多。也就是说,我正在努力使一个简单的登录页面正常工作,并花了几个晚上使用SO,Django文档和各种教程。对于那些只是试图获取登录页面基础知识的人来说,Django文档似乎没有很好的组织,有点压倒性,而且我遇到的大多数SO答案都是旧的。

我使用的这两个教程并没有让我了解我的目标:

Right way of adding user authentication to Django

How to Use Django's Built-in Login System

使用Python 3.5.2,Django 1.10和PostgreSQL 9.6。在我的设置中,localhost:8000是登录页面。用户需要先登录才能查看任何内容。我还有应用/home/results等,但现在我只使用/home。如果他们尝试转到localhost:8000/home,他们将被路由到登录,这样做会将他们带到http://localhost:8000/?next=/home/。所以这很有效。

当我输入凭据时,它会一直将我发送到登录屏幕。转到localhost:8000/home只会做同样的事情。似乎不是在验证。数据库凭据是正确的,用户凭据是正确的,并且在python manage.py shell中与数据库进行通信是正常的。

这是我的简化目录结构:

~/portal-client

project_dir
    apps
        account
            templates
                account
                    login.html
            forms.py
            urls.py
            views.py
        home
            templates
                home
                    home.html
            urls.py
            views.py
        results
    settings.py
    urls.py
scripts
    manage.py
static
templates
    base.html
    footer.html
    title.html

PROJECT_DIR / settings.py

# INSTALLED_APPS, TEMPLATES, STATIC, DATABASES all correct so just this line added
LOGIN_REDIRECT_URL = 'home'

PROJECT_DIR / urls.py

from django.conf.urls import include, url
from django.contrib import admin

from django.contrib.auth import views as auth_views
from account.forms import LoginForm

urlpatterns = [
    url(r'', include('account.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^documents/$', include('documents.urls')),
    url(r'^help/$', include('help.urls')),
    url(r'^home/$', include('home.urls')),
    url(r'^results/$', include('results.urls')),
    url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
    url(r'^login/$', auth_views.login, {'template_name': 'account/login.html', 'authentication_form': LoginForm}, name='login'),
]

主/ views.py

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

# Create your view here.
# The following prohibits access to the website unless authenticated
@login_required(login_url="/")
def home(request):
    return render(request, 'home/home.html')

account / urls.py - 编辑

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.user_login, name='user_login'),
]

account / forms.py - 编辑

from django.contrib.auth.forms import AuthenticationForm
from django import forms

# If you don't do this you cannot use Bootstrap CSS
class LoginForm(AuthenticationForm:
    username = forms.CharField(max_length=50)
    password = forms.CharField(widget=forms.PasswordInput)

    def clean_username(self):
        username = self.cleaned_data.get("username")
    def clean_password(self):
        password= self.cleaned_data.get("password")

account / views.py - 编辑

from django.shortcuts import render
from django.contrib.auth import views
from .forms import LoginForm

# Create your view here.
def user_login(request):

    form = LoginForm(request.POST or None)
    if form.is_valid():
        username = form.cleaned_data['username']
        password = form.cleaned_data['password']

        user = authenticate(username=username, password=password)
        if user is not None:
           login(request, user)
           return httpResponseRedirect('/home')
        else:
           return httpResponseRedirect('/')
    context = {
    "form" : form
     }
    return render(request, "account/login.html", context)   

帐户/ l​​ogin.html的

<form class="form-horizontal" role="form" method="POST" action="{% url 'home' %}">
{% csrf_token %}
    <div class="form-group">
        <label for="email" class="col-md-4 control-label">Username</label>

        <div class="col-md-6">

            {{ form.username }}

        </div>
    </div>

    <div class="form-group">
        <label for="password" class="col-md-4 control-label">Password</label>


        <div class="col-md-6">

            {{ form.password }}

        </div>
    </div>


    <div class="form-group">
        <div class="col-md-6 col-md-offset-4">
            <div class="checkbox">
                <label>
                    <input type="checkbox" name="remember"> Remember Me
                </label>
            </div>
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-8 col-md-offset-4">
            <button type="submit" class="btn btn-primary">
                Login
            </button>

            <a class="btn btn-link" href="url('/password/reset')">
                Forgot Your Password?
            </a>
        </div>
    </div>

</form>

我认为这就是一切!我提前感谢您的帮助!希望继续将这些应用程序放在一起并通过身份验证。

编辑:

我还没读过的一件事是我是否需要对account/models.py文件做任何事情。所有客户数据都在默认的auth_user表中。

另外,想知道django-allauth之类的东西是不是一个好的解决方案。

1 个答案:

答案 0 :(得分:2)

Django附带authentication views,如果可能,你应该使用这些,而不是自己编写。

您已在网址格式中包含内置登录视图。

url(r'^login/$', auth_views.login, {'template_name': 'account/login.html'}, name='login'),

因此您不需要user_login视图,因此我会删除它。我已删除您的自定义身份验证表单,因为它不是必需的。默认身份验证表单已包含用户名和密码字段。您已经破解了clean_方法,因为您没有返回值。

接下来,在模板中修复表单的action。目前,您正在将表单数据提交到home视图。您应该将其发送到login视图。

<form class="form-horizontal" role="form" method="POST" action="{% url 'login' %}">

最后,我会在您的设置中添加LOGIN_URL = 'login',然后您可以将使用login_required的代码简化为以下内容:

@login_required
def home(request):
    ...