被解放的姜戈06 假作真时
之前了解了:
- 创建Django项目
- 数据库
- 模板
- 表格提交
- admin管理页面
上面的功能模块允许我们做出一个具有互动性的站点,但无法验证用户的身份。我们这次了解用户验证部分。通过用户验证,我们可以根据用户的身份,提供不同的服务。
一个Web应用的用户验证是它的基本组成部分。我们在使用一个应用时,总是从“登录”开始,到“登出”结束。另一方面,用户验证又和网站安全、数据库安全息息相关。HTTP协议是无状态的,但我们可以利用储存在客户端的cookie或者储存在服务器的session来记录用户的访问。
Django有管理用户的模块,即django.contrib.auth。你可以在mysite/settings.py里看到,这个功能模块已经注册在INSTALLED_APPS中。利用该模块,你可以直接在逻辑层面管理用户,不需要为用户建立模型,也不需要手工去实现会话。
“为了救你的爱人出来,我们要演一场戏。”
创建用户
你可以在admin页面直接看到用户管理的对话框,即Users。从这里,你可以在这里创建、删除和修改用户。点击Add增加用户daddy,密码为daddyiscool。
在admin页面下,我们还可以控制不同用户组对数据库的访问权限。我们可以在Groups中增加用户组,设置用户组对数据库的访问权限,并将用户加入到某个用户组中。
在这一章节中,我们创立一个新的app,即users。下文的模板和views.py,都针对该app。
"你这套新衣服,还真像那么回事",德国人说。
用户登录
我们建立一个简单的表格。用户通过该表格来提交登陆信息,并在Django服务器上验证。如果用户名和密码正确,那么登入用户。
我们首先增加一个登录表格:
<form role="form" action="/login" method="post">
<label>Username</label>
<input type="text" name='username'>
<label>Password</label>
<input name="password" type="password">
<input type="submit" value="Submit">
</form>
我们在views.py中,定义处理函数user_login(),来登入用户:
# -*- coding: utf-8 -*-
from django.shortcuts import render, redirect
from django.core.context_processors import csrf
from django.contrib.auth import *
def user_login(request):
'''
login
'''
if request.POST:
username = password = ''
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return redirect('/')
ctx = {}
ctx.update(csrf(request))
return render(request, 'login.html',ctx)
上面的authenticate()函数,可以根据用户名和密码,验证用户信息。而login()函数则将用户登入。它们来自于django.contrib.auth。
作为替换,我们可以使用特别的form对象,而不自行定义表格。这将让代码更简单,而且提供一定的完整性检验。
练习. 使用contrib.auth.forms.AuthenticationForm。来简化上面的模板和处理函数。
德国人还是不忘一再叮嘱,"记住,我们可不是什么赏金猎人。"
登出
有时用户希望能销毁会话。我们可以提供一个登出的URL,即/users/logout。登入用户访问该URL,即可登出。在views.py中,增加该URL的处理函数:
# -*- coding: utf-8 -*-
from django.shortcuts import redirect
def user_logout(request):
'''
logout
URL: /users/logout
'''
logout(request)
return redirect('/')
我们修改urls.py,让url对应user_logout()。访问http://127.0.0.1/users/logout,就可以登出用户。
德国人压低声音,“哦,我是来救你的,我们要演一出戏。”
views.py中的用户
上面说明了如何登入和登出用户,但还没有真正开始享受用户验证带来的好处。用户登陆的最终目的,就是为了让服务器可以区别对待不同的用户。比如说,有些内容只能让登陆用户看到,有些内容则只能让特定登陆用户看到。我们下面将探索如何实现这些效果。
在Django中,对用户身份的检验,主要是在views.py中进行。views.py是连接模型和视图的中间层。HTTP请求会转给views.py中的对应处理函数处理,并发回回复。在views.py的某个处理函数准备HTTP回复的过程中,我们可以检验用户是否登陆。根据用户是否登陆,我们可以给出不同的回复。最原始的方式,是使用if式的选择结构:
# -*- coding: utf-8 -*-
from django.http import HttpResponse
def diff_response(request):
if request.user.is_authenticated():
content = "<p>my dear user</p>"
else:
content = "<p>you wired stranger</p>"
return HttpResponse(content)
可以看到,用户的登录信息包含在request.user中,is_authenticated()方法用于判断用户是否登录,如果用户没有登录,那么该方法将返回false。该user对象属于contrib.auth.user类型,还有其它属性可供使用,比如
属性 |
功能 |
---|---|
get_username() |
返回用户名 |
set_password() |
设置密码 |
get_fullname() |
返回姓名 |
last_login |
上次登录时间 |
date_joined |
账户创建时间 |
练习. 实验上面的处理函数的效果。
在Django中,我们还可以利用装饰器,根据用户的登录状况,来决定views.py中处理函数的显示效果。相对于上面的if结构,装饰器使用起来更加方便。下面的user_only()是views.py中的一个处理函数。
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
@login_required
def user_only(request):
return HttpResponse("<p>This message is for logged in user only.</p>")
注意上面的装饰器login_required,它是Django预设的装饰器。user_only()的回复结果只能被登录用户看到,而未登录用户将被引导到其他页面。
Django中还有其它的装饰器,用于修饰处理函数。相应的http回复,只能被特殊的用户看到。比如user_passes_test,允许的用户必须满足特定标准,而这一标准是可以用户自定义的。比如下面,在views.py中增添:
from django.contrib.auth.decorators import user_passes_test
from django.http import HttpResponse
装饰器带有一个参数,该参数是一个函数对象name_check。当name_check返回真值,即用户名为vamei时,specific_user的结果才能被用户看到。
德国人羞涩的笑笑,“我确实对她有那么点好感。”
模板中的用户
进一步,用户是否登陆这一信息,也可以直接用于模板。比较原始的方式是把用户信息直接作为环境数据,提交给模板。然而,这并不是必须的。事实上,Django为此提供了捷径:我们可以直接在模板中调用用户信息。比如下面的模板:
{% if user.is_authenticated %}
<p>Welcome, my genuine user, my true love.</p>
{% else %}
<p>Sorry, not login, you are not yet my sweetheart. </p>
{% endif %}
不需要环境变量中定义,我们就可以直接在模板中引用user。这里,模板中调用了user的一个方法,is_authenticated,将根据用户的登录情况,返回真假值。需要注意,和正常的Python程序不同,在Django模板中调用方法并不需要后面的括号。
练习. 增加处理函数,显示该模板,然后查看不同登录情况下的显示结果。
管家冷不丁的说,“你认识他们?!”
用户注册
我们上面利用了admin管理页面来增加和删除用户。这是一种简便的方法,但并不能用于一般的用户注册的情境。我们需要提供让用户自主注册的功能。这可以让站外用户提交自己的信息,生成自己的账户,并开始作为登陆用户使用网站。
用户注册的基本原理非常简单,即建立一个提交用户信息的表格。表格中至少包括用户名和密码。相应的处理函数提取到这些信息后,建立User对象,并存入到数据库中。
我们可以利用Django中的UserCreationForm,比较简洁的生成表格,并在views.py中处理表格:
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
from django.core.context_processors import csrf
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return redirect("/")
else:
form = UserCreationForm()
ctx = {'form': form}
ctx.update(csrf(request))
return render(request, "register.html", ctx)
相应的模板register.html如下:
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Register">
</form>
“骗子,你们这些骗子”,庄园主怒吼着。
总结
正如我们上面提到的,用户登陆系统的最大功能是区分登入和未登入用户,向他们提供不同的内容和服务。
我们看到了用户验证的基本流程,也看到了如何在views.py和模板中区分用户。
两杆枪,一支指着德国人,一支指着姜戈。
- NSCopying和NSCoding对象序列化反序列化基础详解你要知道的NSCopying、NSCoding协议及对象序列化和反序列化都在这里
- KVO 正确使用姿势进阶及底层实现你要知道的KVC、KVO、Delegate、Notification都在这里
- iOS多线程——你要知道的NSOperation都在这里你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里
- iOS多线程——你要知道的NSThread都在这里你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里
- KVO、Delegate、Notification 区别及相关使用场景你要知道的KVC、KVO、Delegate、Notification都在这里
- Core ML简介及实时目标检测及Caffe TensorFlow coremltools模型转换
- iOS网络——NSURLSession详解及SDWebImage源码解析你要知道的NSURLSession都在这里
- BZOJ3585: mex(主席树)
- 01.LoT.UI 前后台通用框架分解系列之——小图片背景全屏显示(可自动切换背景)
- 02.LoT.UI 前后台通用框架分解系列之——灵活的菜单栏
- 05.LoT.UI 前后台通用框架分解系列之——漂亮的时间选择器
- 06.LoT.UI 前后台通用框架分解系列之——浮夸的图片上传
- 07.LoT.UI 前后台通用框架分解系列之——轻巧的文本编辑器
- 07.LoT.UI 前后台通用框架分解系列之——强大的文本编辑器
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 猿思考系列5——一文明白java和微商那点儿事儿
- 猿思考系列8——缓存的套路也就这些
- 猿思考系列9——一文获取隐藏逻辑挖掘办法
- 猿蜕变系列1——春天的故事
- 猿蜕变系列2——一文搞懂spring的花式DI
- 猿蜕变系列3——SpringMVC之初体验
- 猿蜕变4——一文获取web框架正确学习套路
- 猿蜕变系列5——一文搞懂Controller的花式编写
- 猿蜕变系列6——一文掌握springMVC必会技巧
- ModuleNotFoundError: No module named ‘__main__.XX‘;
- 猿蜕变系列7——也说说springMVC上传姿势
- 猿蜕变系列8——一文搞懂Interceptor操纵姿势
- 猿蜕变9——一文搞定SpringMVC的RESTFul套路
- 猿蜕变10——一文学会ORM的正确打开姿势
- 猿蜕变11——一文掌握mybatis全局玩儿法