用户已经能够在我们的网站注册了,注册就是为了登录,接下来我们为用户提供登录功能。和注册不同的是,Django 已经为我们写好了登录功能的全部代码,我们不必像之前处理注册流程那样费劲了。只需几分钟的简单配置,就可为用户提供登录功能。接下来就来看看如何使用内置的登录功能。

引入内置的 URL 模型

Django 内置的登录、修改密码、找回密码等视图函数对应的 URL 模式位于 django.contrib.auth.urls.py 中,首先在工程的 urls.py 文件里包含这些 URL 模式。打开 django_auth_example/ 目录下的 urls.py 文件,将 django.contrib.auth.urls.py 包含进来:

django_auth_example/urls.py

from django.conf.urls import url, include
from django.contrib import admin urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^users/', include('users.urls')),
# 将 auth 应用中的 urls 模块包含进来
url(r'^users/', include('django.contrib.auth.urls')),
]

这将包含以下的 URL 模式:

^users/login/$ [name='login']
^users/logout/$ [name='logout']
^users/password_change/$ [name='password_change']
^users/password_change/done/$ [name='password_change_done']
^users/password_reset/$ [name='password_reset']
^users/password_reset/done/$ [name='password_reset_done']
^users/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$ [name='password_reset_confirm']
^users/reset/done/$ [name='password_reset_complete']

设置模板路径

默认的登录视图函数渲染的是 registration/login.html 模板,因此需要在 templates/ 目录下新建一个 registration 文件夹,再在 registration/ 目录下新建 login.html 模板文件。此时目录结构为:

django_auth_example/
manage.py
django_auth_example/
__init__.py
settings.py
urls.py
wsgi.py
templates/
users/
register.html
registration/
login.html

编写登录模板

登录模板的代码和注册模板的代码十分类似:

registration/login.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>登录</title>
<link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
<style>
.errorlist {
color: red;
}
</style>
</head>
<body>
<div class="flex-center">
<div class="container">
<div class="flex-center">
<div class="unit-1-2 unit-1-on-mobile">
<h3>登录</h3>
<form class="form" action="{% url 'login' %}" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
{% if field.help_text %}
<p class="help text-small text-muted">{{ field.help_text|safe }}</p>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">登录</button>
</form>
<div class="flex-left top-gap text-small">
<div class="unit-2-3"><span>没有账号?<a href="{% url 'users:register' %}">立即注册</a></span></div>
<div class="unit-1-3 flex-right"><span><a href="reset_password.html">忘记密码?</a></span></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

为了登录页面的美观我引入了 mobi.css 提供样式支持,其它代码请忽略,我们只关注表单部分的代码。

<form class="form" action="{% url 'login' %}" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
{% if field.help_text %}
<p class="help text-small text-muted">{{ field.help_text|safe }}</p>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">登录</button>
</form>

循环表单字段、渲染控件、渲染帮助信息等在注册表单部分已经讲过,登录表单中只引入了一个新的东西:{{ form.non_field_errors }},这显示的同样是表单错误,但是显示的表单错误是和具体的某个表单字段无关的。相对 {{ field.errors }},这个则显示的是具体某个字段的错误。比如对于字段 username,如果用户输入的 username 不符合要求,比如太长了或者太短了,表单会在 username 下方渲染这个错误。但有些表单错误不和任何具体的字段相关,比如用户输入的用户名和密码无法通过验证,这可能是用户输入的用户名不存在,也可能是用户输入的密码错误,因此这个错误信息将通过 {{ form.non_field_errors }} 渲染。

注意:你可能觉得用户名不存在错误和 username 字段有关,密码错误和 password 字段有关。但是在现代的用户认证系统中,我们不为用户提供这么详细的信息,只是笼统地告知用户名不存在或者密码错误。这能提高一些用户账户的安全性。

此外登录表单的 action 属性的值是 {% url 'login' %},即 auth 应用下的 login 视图函数对应的 URL,用户提交的表单数据将提交给这个 URL,Django 调用 login 视图函数来处理。

不要忘了加 {% csrf_token %} 模板标签。

现在打开开发服务器,在浏览器输入 http://127.0.0.1:8000/users/login/,你将看到一个用户登陆表单。

故意使用一个不存在的账户登录,或者故意输错密码,你将看到表单渲染的非字段相关的错误。

如果用户登录成功,你会发现跳转到了 http://127.0.0.1:8000/accounts/profile/ 页面。由于我们没有写任何视图函数处理这个 URL,所以看到一个 404 错误。不过没有关系,我们目前只关注用户是否已经登录。

如何在模板中判断用户是否已经登录

在模板中判断用户是否已经登录非常简单,使用 {% if user.is_authenticated %} 条件判断即可。借此机会,我们来处理一下网站首页。

在 user/views.py 写一个首页视图函数:

user/views.py 

def index(request):
return render(request, 'index.html')

为这个视图函数配置 URL 模式,在 django_auth_example/urls.py 进行配置:

from django.conf.urls import url, include
from django.contrib import admin from users import views urlpatterns = [
url(r'^admin/', admin.site.urls),
# 别忘记在顶部引入 include 函数
url(r'^users/', include('users.urls')),
url(r'^users/', include('django.contrib.auth.urls')),
# 别忘记在顶部引入 views 模块
url(r'^$', views.index, name='index')
]

注意:直接在项目的 urls.py 中配置 URL 是不推荐的,应该在应用的 urls.py 下进行配置,然后在项目的 urls.py 中通过 include 函数包含。不过这里作为示例情况特殊,所以姑且这样做。

由于视图渲染了 index.html 文件,因此在 templates/ 目录下建一个 index.html 模板文件(注意我们没有把它放在 users/ 下,也没放在 registration/ 下)。然后写上下面的代码:

templates/index.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>首页</title>
<link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
</head>
<body>
<div class="flex-center">
<div class="container">
<div>
<h1 class="logo"><a href="{% url 'index' %}">Django Auth Example</a></h1>
{% if user.is_authenticated %}
<p>你已登录,欢迎你:<a href="#">{{ user.username }}</a></p>
{% else %}
<p>你还没有登录,请
<button class="btn btn-default"><a href="{% url 'login' %}">登录</a></button>
或者
<button class="btn btn-default"><a href="{% url 'users:register' %}">注册</a></button>
</p>
{% endif %}
</div>
</div>
</div>
</body>
</html>

为了页面的美观,我引入了 mobi.css 提供样式支持。其它代码请忽略,重点只关注用户登录验证部分:

{% if user.is_authenticated %}
<p>你已登录,欢迎你:<a href="#">{{ user.username }}</a></p>
{% else %}
<p>你还没有登录,请
<button class="btn btn-default"><a href="{% url 'login' %}">登录</a></button>
或者
<button class="btn btn-default"><a href="{% url 'users:register' %}">注册</a></button>
</p>
{% endif %}

user.is_authenticated 当用户已经登录时返回 True,否则返回 False。所以已登录的用户将看到欢迎页面,否则将看到登录注册按钮。

你也许奇怪我们在 index 视图中并没有传递 user 模板变量给 index.html,为什么可以在模板中引用 user 呢?这是因为 Django 的 auth 应用为我们设置了模板常量,所以在任何模板中都可以引用 {{ user }}。此外,我们之前提过的 django.contrib.auth.middleware.AuthenticationMiddleware 为所有的请求 request 绑定了一个 user 属性。所以在模板中引用 {{ user }} 和 {{ request.user }} 是等价。

OK 了!不过目前为止,如果你已经登录过了,想要看看未登录的效果会变得比较困难,因为我们还无法注销登录。下面就来给网站添加注销登录的功能吧!

最新文章

  1. Servlet---RequestDispatcher.include方法
  2. @RequestMapping(value = &quot;{adminPath}&quot;)
  3. Android之Notification介绍
  4. Unity手游之路&lt;十&gt;自动寻路Navmesh之跳跃,攀爬,斜坡
  5. 9.8---硬币问题(CC150)
  6. Tips11:用[Rang]来限制Inspector中的变量
  7. jws操作
  8. Eclipse混淆文件导入Android Studio Gradle编译报input jar file is specified twice
  9. 《Java程序员面试笔试宝典》之 instanceof有什么作用
  10. 利用Azure backup备份和恢复Azure虚拟机(1)
  11. php部分学习笔记
  12. Python 第四天
  13. Thinkphp3.2.3加载外部类并调用类里面的方法 获取token
  14. Ubuntu下无法输入中文问题解决
  15. Jtest的简单使用
  16. HTTP RFC解析
  17. 带你从零学ReactNative开发跨平台App开发(三)
  18. Sequelize-nodejs-4-Model usage
  19. IDEA/Git 设置多个push远程仓库或者同时提交多个push仓库
  20. python---Django中模型类中Meta元对象了解

热门文章

  1. 获取当前View
  2. static、final修饰符、内部类
  3. hadoop权威指南(第四版)要点翻译(4)——Chapter 3. The HDFS(1-4)
  4. 【DB2】判断连续时间,如果间断则新增一条记录
  5. python导入模块的两种方式
  6. CentOS源码编译安装Nginx
  7. Build System 和Test Framework overview总结
  8. vue的组件(先学习其他的ES6知识,之后再看这个) (未完)
  9. unity, OnTriggerEnter2D不触发
  10. andorid HTTPS 不需要证书 VolleyEror: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not fou