categories:
- Django
参考书籍:《Python编程从入门到实践》—Eric Matthes
(效果图在底部)
目标:开放用户注册,提供登录和注销的功能。并添加身份验证系统
应用程序users
使用命令startapp创建一个名为users的应用程序
在命令行输入(先激活环境ll_env/Scripts/activate
)
python manage.py startapp users
完毕后出现user文件夹
users目录下出现admin.py _init_.py migrations models.py tests.py views.py 等文件
将应用程序users添加到settings.py中
向settings.py中的INSTALL_APPS添加
'users',
这样Django将把应用程序users包含到项目中
使users定义的URL被包含
在learning_log/urls.py(不是learning_logs)中的urlpatterns添加
url(r'^users/', include(('users.urls', "users"), namespace="users")),
这样就包含了应用程序users中的文件urls.py。这行代码与任何以任何单词users打头的URL(如:http://localhost:8000/users/login/)都匹配。此外我们还创建了命名空间’users’,以便将应用程序learning_logs的URL同users的URL区分开。
登录页面
在learning_log/users的文件夹中,新建一个名为urls.py的文件
"""为应用程序users定义URL模式"""
from django.conf.urls import url
from django.contrib.auth.views import LoginView
from . import views
urlpatterns = [
#登录页面
url(r'^login/$',LoginView.as_view(template_name='users/login.html'),name='login')
]
- 首先导入了默认视图login,登录页面与http://localhost:8000/users/login/匹配。这个模板在users中。
模板login.html
虽然请求登录页面时,Django使用默认视图login,但我们依然要为这个页面提供模板。
与learning_logs中的模板类似,我们新建这样的目录learning_log/users/templates/users,并在其中添加各种html模板。
新建login.html
{% extends "learning_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url 'users:login' %}">
{% csrf_token %}
{{form.as_p}}
<button name="submit">log in</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index'%}" />
</form>
{% endblock content %}
- 继承了base.html,确保登录页面的外观与网站其他页面相同。
- 如果输入的用户名-密码与数据库中的不匹配,那么表单的errors的属性被设置,显示一条错误消息
- 让登录视图处理表单,因此action设置为登录页面的URL。登录视图将一个表单发送给模板,在模板中我们显示一个表单并添加一个提交按钮。
- 最后包含一个隐藏的表单元素next,其中的实参value在登录成功后重定向到主页。
链接到登录页面
在learning_logs目录下的base.html中添加到登录页面的链接,让所有的页面都包含它。
...
<a href="{% url 'learning_logs:topics' %}">Topics</a> -
{% if user.is_authenticated %}
Hello, {{users.username}}.
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
...
在Django身份验证系统中,每个模板都可以使用变量user,这个变量有一个is_authenticated属性:如果用户已经登录那么属性为True,否则为False。所以我们根据这两种状态向用户显示不同信息。
注意!!!如果此时login的界面无法正常打开比如django.template.exceptions.TemplateDoesNotExist: users/login.htm
的错误,检查你的setting.py文件的DIRS,更改为DIRS': [os.path.join(BASE_DIR,'templates')],
>
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
注销
不创建一个用于注销的页面,只需创建一个按钮单机便能返回主页。
添加步骤:定义一个URL模式->编写一个视图函数->在base.html中添加一个注销链接
定义注销的URL
在users/urls.py中添加
#注销
url(r'^logout/$',views.logout_view,name='logout'),
URL模式将请求发送给函数logout_view()。
视图函数logout_view()
导入Django函数logout()并调用它,再重定向到主页。
在uses/views.py修改
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth import logout
# Create your views here.
def logout_view(request):
"""注销用户"""
logout(request)
return HttpResponseRedirect(reverse('learning_logs:index'))
链接到注销视图
在base.html中修改,让每个页面都包含它
放在标签{% if user.is_authenticated %}
中,使得用户登录后才能看到
...
{% if user.is_authenticated %}
Hello, {{user.username}}.
<a href="{% url 'users:logout' %}">log out</a>
...
注册页面
使用Django提供的表单UserCreationForm创建一个注册的页面
定义URL
在users/urls.py中添加
#注册
url(r'^register/$',views.register,name='register'),
这个模式与URL http://localhost:8000/users/register/匹配
视图函数register()
在注册页面首次被请求时,视图函数register()需要显示一个空的注册表单,并在用户提交表单时对其进行处理。注册成功时还能进行自动登录。
在users/views.py中添加
from django.contrib.auth import login,logout,authenticate
from django.contrib auth.forms import UserCreationForm
def register(request):
"""注册新用户"""
if request.method != 'POST':
#显示空的注册表单
form = UserCreationForm()
else:
#处理填好的表单
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
#让用户自动登录,再重定向到主页
authenticate_user = authenticate(username=new_user.usrename,
password=request.POST['password1'])
login(request,authenticate_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form':form}
return render(request,'users/register.html',context)
-
我们首先导入了函数render(),然后导入了函数login()和authenticate(),以便在用户正确地填写了注册信息时让其自动登录。我们还导入了默认表单UserCreationForm。在函数register()中,我们检查要响应的是否是POST请求。如果不是,就创建一个UserCreationForm实例,且不给它提供任何初始数据
-
如果响应的是POST请求,我们就根据提交的数据创建一个UserCreationForm实例,并检查这些数据是否有效:就这里而言,是用户名未包含非法字符,输入的两个密码相同,以及用户没有试图做恶意的事情。 如
-
如果提交的数据有效,我们就调用表单的方法save(),将用户名和密码的散列值保存到数据 库中。方法save()返回新创建的用户对象,我们将其存储在new_user中。
-
保存用户的信息后,我们让用户自动登录,这包含两个步骤。首先,我们调用authenticate(),并将实参new_user.username和密码传递给它。用户注册时,被要求输入密码两次;由于表单是有效的,我们知道输入的这两个密码是相同的,因此可以使用其中任何一个。在这里,我们从表单的POST数据中获取与键’password1’相关联的值。如果用户名和密码无误,方法authenticate()将返回一个通过了身份验证的用户对象,而我们将其存储在authenticated_user中。接下来,我们调用函数login(),并将对象request和authenticated_user传递给它,这将为新用户创建有效的会话。最后,我们将用户重定向到主页,其页眉中显示了一条个性化的问候语,让用户知道注册成功了。
注册模板
在login.html目录下新建register.html
{% extends "learning_logs/base.html" %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">register</button>>
<input type="hidden" name="next" value="{% url 'learning_logs:index'%}"/>
</form>
{% endblock content %}
这里也使用了方法as_p,让Django在表单中正确地显示所有的字段,包括错误消息——如果用户没有正确地填写表单。
链接到注册页面
在base.html中修改
{% else %}
<a href="{% url 'users:register' %}">register</a> -
<a href="{% url 'users:login' %}">log in</a>
效果图: