Skip to content

Commit

Permalink
tornado 6
Browse files Browse the repository at this point in the history
  • Loading branch information
qiwsir committed Jun 1, 2015
1 parent f4caa96 commit d20c79c
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 1 deletion.
134 changes: 134 additions & 0 deletions 308.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
>我亲爱的弟兄们,这是你们所知道的。但你们个人要快快地听,慢慢地说,慢慢地动怒,因为人的怒气并不成就神的义。所以,你们要脱去一切的污秽和盈余的邪恶,存温柔的心领受那所栽种的道,就是能救你们灵魂的道。(JAMES 1:19-21)
#用tornado做网站(6)

[上一节](./307.md)中已经对安全问题进行了描述,另外一个内容是不能忽略的,那就是用户登录之后,对当前用户状态(用户是否登录)进行判断。

##用户验证

用户登录之后,当翻到别的目录中时,往往需要验证用户是否处于登录状态。当然,一种比较直接的方法,就是在转到每个目录时,都从cookie中把用户信息,然后传到后端,跟数据库验证。这不仅是直接的,也是基本的流程。但是,这个过程如果总让用户自己来做,框架的作用就显不出来了。tornado就提供了一种用户验证方法。

为了后面更工程化地使用tornado编程。需要将前面的已经有的代码进行重新梳理。我只是将有修改的文件代码写出来,不做过多解释,必要的有注释,相信读者在前述学习基础上,能够理解。

在handler目录中增加一个文件,名称是base.py,代码如下:

#! /usr/bin/env python
# coding=utf-8

import tornado.web

class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("user")

在这个文件中,目前只做一个事情,就是建立一个名为BaseHandler的类,然后在里面放置一个方法,就是得到当前的cookie。在这里特别要向读者说明,在这个类中,其实还可以写不少别的东西,比如你就可以将数据库连接写到这个类的初始化`__init__()`方法中。因为在其它的类中,我们要继承这个类。所以,这样一个架势,就为读者以后的扩展增加了冗余空间。

然后把index.py文件改写为:

#!/usr/bin/env python
# coding=utf-8

import tornado.escape
import methods.readdb as mrd
from base import BaseHandler

class IndexHandler(BaseHandler): #继承base.py中的类BaseHandler
def get(self):
usernames = mrd.select_columns(table="users",column="username")
one_user = usernames[0][0]
self.render("index.html", user=one_user)

def post(self):
username = self.get_argument("username")
password = self.get_argument("password")
user_infos = mrd.select_table(table="users",column="*",condition="username",value=username)
if user_infos:
db_pwd = user_infos[0][2]
if db_pwd == password:
self.set_current_user(username) #将当前用户名写入cookie,方法见下面
self.write(username)
else:
self.write("-1")
else:
self.write("-1")

def set_current_user(self, user):
if user:
self.set_secure_cookie('user', tornado.escape.json_encode(user)) #注意这里使用了tornado.escape.json_encode()方法
else:
self.clear_cookie("user")

class ErrorHandler(BaseHandler): #增加了一个专门用来显示错误的页面
def get(self): #但是后面不单独讲述,读者可以从源码中理解
self.render("error.html")

在index.py的类IndexHandler中,继承了BaseHandler类,并且增加了一个方法set_current_user()用于将用户名写入cookie。请读者特别注意那个tornado.escape.json_encode()方法,其功能是:

>tornado.escape.json_encode(value)
> JSON-encodes the given Python object.
如果要查看源码,可以阅读:[http://www.tornadoweb.org/en/branch2.3/escape.html](http://www.tornadoweb.org/en/branch2.3/escape.html)

这样做的本质是把user转化为json,写入到了cookie中。如果从cookie中把它读出来,使用user的值时,还会用到:

>tornado.escape.json_decode(value)
> Returns Python objects for the given JSON string
它们与[json模块中的dump()、load()](./227.md)功能相仿。

接下来要对user.py文件也进行重写:

#!/usr/bin/env python
# coding=utf-8

import tornado.web
import tornado.escape
import methods.readdb as mrd
from base import BaseHandler

class UserHandler(BaseHandler):
@tornado.web.authenticated
def get(self):
#username = self.get_argument("user")
username = tornado.escape.json_decode(self.current_user)
user_infos = mrd.select_table(table="users",column="*",condition="username",value=username)
self.render("user.html", users = user_infos)

在get()方法前面添加`@tornado.web.authenticated`,这是一个装饰器,它的作用就是完成tornado的认证功能,即能够得到当前合法用户。在原来的代码中,用`username = self.get_argument("user")`方法,从url中得到当前用户名,现在把它注释掉,改用`self.current_user`,这是和前面的装饰器配合使用的,如果它的值为假,就根据setting中的设置,寻找login_url所指定的目录(请关注下面对setting的配置)。

由于在index.py文件的set_current_user()方法中,是将user值转化为json写入cookie的,这里就得用`username = tornado.escape.json_decode(self.current_user)`解码。得到的username值,可以被用于后一句中的数据库查询。

application.py中的setting也要做相应修改:

#!/usr/bin/env python
# coding=utf-8

from url import url

import tornado.web
import os

setting = dict(
template_path = os.path.join(os.path.dirname(__file__), "templates"),
static_path = os.path.join(os.path.dirname(__file__), "statics"),
cookie_secret = "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=",
xsrf_cookies = True,
login_url = '/',
)

application = tornado.web.Application(
handlers = url,
**setting
)

与以前代码的重要区别在于`login_url = '/',`,如果用户不合法,根据这个设置,会返回到首页。当然,如果有单独的登录界面,比如是`/login`,也可以`login_url = '/login'`

如此完成的是用户登录到网站之后,在页面转换的时候实现用户认证。

为了演示本节的效果,我对教程的源码进行修改。读者在阅读的时候,可以参照源码。

------

[总目录](./index.md)   |   [上节:用tornado做网站(5)](./307.md)   |   [下节:用tornado做网站(7)](./309.md)

如果你认为有必要打赏我,请通过支付宝:**[email protected]**,不胜感激。
120 changes: 119 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,121 @@
#This is for everyone.

#From beginner to master.
>In the begning when God created the heavens and the earth. the earth was a formless void and darkness covered the face of the deep, while a wind from God swept over the face of the waters. Then God said,"Let there be light"; and there was light. And God saw that the light was good; and God separated the light from the darkness. (GENESIS 1:1-4)
#《零基础学python》(第二版):From beginner to master.

#第壹季 基础

##第零章 预备

1. [关于python的故事](./01.md)
2. [从小工到专家](./02.md)
3. [安装python的开发环境](./03.md)
4. [集成开发环境](./101.md)==>集成开发环境;python的IDE

##第壹章 基本数据类型

1. [数和四则运算](./102.md)==>整数和浮点数;变量;整数溢出问题;
2. [除法](./103.md)==>整数、浮点数相除;`from __future__ import division`;余数;四舍五入;
3. [常用数学函数和运算优先级](./104.md)==>math模块,求绝对值,运算优先级
4. [写一个简单程序](./105.md)==>程序和语句,注释
5. [字符串(1)](./106.md)==>字符串定义,转义符,字符串拼接,str()与repr()区别
6. [字符串(2)](./107.md)==>raw_input,print,内建函数,原始字符串,再做一个小程序
7. [字符串(3)](./108.md)==>字符串和序列,索引,切片,基本操作
8. [字符串(4)](./109.md)==>字符串格式化,常用的字符串方法
9. [字符编码](./110.md)==>编码的基础知识,python中避免汉字乱码
10. [列表(1)](./111.md)==>列表定义,索引和切片,列表反转,元素追加,基本操作
11. [列表(2)](./112.md)==>列表append/extend/index/count方法,可迭代的和判断方法,列表原地修改
12. [列表(3)](./113.md)==>列表pop/remove/reverse/sort方法
13. [回顾列表和字符串](./114.md)==>比较列表和字符串的相同点和不同点
14. [元组](./115.md)==>元组定义和基本操作,使用意义
15. [字典(1)](./116.md)==>字典创建方法、基本操作(长度、读取值、删除值、判断键是否存在)
16. [字典(2)](./117.md)==>字典方法:copy/deepcopy/clear/get/setdefault/items/iteritems/keys/iterkeys/values/itervalues/pop/popitem/update/has_key
17. [集合(1)](./118.md)==>创建集合,集合方法:add/update,pop/remove/discard/clear,可哈希与不可哈希
18. [集合(2)](./119.md)==>不可变集合,集合关系

##第贰章 语句和文件

1. [运算符](./120.md)==>算数运算符,比较运算符,逻辑运算符/布尔类型
2. [语句(1)](./121.md)==>print, import, 赋值语句、增量赋值
3. [语句(2)](./122.md)==>if...elif...else语句,三元操作
4. [语句(3)](./123.md)==>for循环,range(),循环字典
5. [语句(4)](./124.md)==>并行迭代:zip(),enumerate(),list解析
6. [语句(5)](./125.md)==>while循环,while...else,for...else
7. [文件(1)](./126.md)==>文件打开,读取,写入
8. [文件(2)](./127.md)==>文件状态,read/readline/readlines,大文件读取,seek
9. [迭代](./128.md)==>迭代含义,iter()
10. [练习](./129.md)==>通过四个练习,综合运用以前所学
11. [自省](./130.md)==>自省概念,联机帮助,dir(),文档字符串,检查对象,文档

##第叁章 函数

1. [函数(1)](./201.md)==>定义函数方法,调用函数方法,命名方法,使用函数注意事项
2. [函数(2)](./202.md)==>函数返回值,函数文档,形参和实参,命名空间,全局变量和局部变量
3. [函数(3)](./203.md)==>收集参数:`*``**`,及其逆过程,复习参数知识
4. [函数(4)](./204.md)==>递归和filter、map、reduce、lambda、yield
5. [函数练习](./205.md)==>解一元二次方程,统计考试成绩,找素数

#第贰季 进阶

##第肆章 类

1. [类(1)](./206.md)==>类的初步认识和基本概念理解:问题空间、对象、面向对象、类和实例化类
2. [类(2)](./207.md)==>新式类和旧式类,类的命名,构造函数,实例化及方法和属性,self的作用
3. [类(3)](./208.md)==>类属性和实例属性,类内外数据流转,命名空间、作用域
4. [类(4)](./209.md)==>继承,多重继承,super函数
5. [类(5)](./210.md)==>静态方法和类方法,两者的区别,类的文档
6. [多态和封装](./211.md)==>多态,封装和私有化
7. [特殊方法(1)](./212.md)==>`__dict__``__slots__`
8. [特殊方法(2)](./213.md)==>`__getattr__`,`__setattr__`以及查找属性顺序
9. [迭代器](./214.md)==>迭代器方法`__iter__`,`netx()`
10. [生成器](./215.md)==>生成器定义,yield,生成器方法

##第伍章 错误和异常

1. [错误和异常(1)](./216.md)==>什么是错误和异常,常见异常类型,处理异常(try...except...)
2. [错误和异常(2)](./217.md)==>处理多个异常,else子句,finally子句
3. [错误和异常(3)](./218.md)==>assert断言,异常小结

##第陆章 模块

1. [编写模块](./219.md)==>模块是程序,模块的位置
2. [标准库(1)](./220.md)==>引用模块的方式,dir()查看属性和方法,模块文档和帮助
3. [标准库(2)](./221.md)==>sys,copy
4. [标准库(3)](./222.md)==>os模块:操作文件、目录,查看修改属性,执行系统命令,打开网页
5. [标准库(4)](./223.md)==>堆的基本知识,heapq模块,deque模块
6. [标准库(5)](./224.md)==>calendar模块、time模块、datetime模块
7. [标准库(6)](./225.md)==>urllib模块、urllib2模块
8. [标准库(7)](./226.md)==>xml.etree.ElementTree模块:遍历查询、增删改查xml,应用实例
9. [标准库(8)](./227.md)==>json模块:dumps(),loads(),dump(),load(),自定义类型数据的json编码和解码
10. [第三方库](./228.md)==>第三方库的模块安装方法,以requests模块为例说明

##第柒章 保存数据

1. [将数据存入文件](./229.md)==>pickle模块,shelve模块
2. [MySQL数据库(1)](./230.md)==>MySQL概况,安装,python连接MySQL模块和方法
3. [MySQL数据库(2)](./231.md)==>连接对象方法,游标对象方法:数据库的增删改查基本操作
4. [MongoDB数据库](./232.md)==>mongodb的安装启动,pymongo模块:连接客户端,数据库的增删改查操作
5. [SQLite数据库](./233.md)==>通过sqlite3模块操作SQLite数据库:连接对象方法,游标对象方法,数据库增删改查
6. [电子表格](./234.md)==>python操作Excel文件的第三方库openpyxl使用方法,以及其它与Excel相关的第三方库

#第叁季 实战

0. [](./300.md)

##第捌章 用Tornado做网站

1. [为做网站而准备](./301.md)==>开发框架,python的常用web框架,tornado框架介绍和安装
2. [分析Hello](./302.md)==>发布tornado做的网站,并剖析基本结构
3. [用tornado做网站(1)](./303.md)==>网站的基本结构,一个基于tornado框架的网站架子
4. [用tornado做网站(2)](./304.md)==>前端模板,静态文件引入
5. [用tornado做网站(3)](./305.md)==>ajax传输数据,get_argument()接收数据,验证用户名和密码
6. [用tornado做网站(4)](./306.md)==>render()方法使用,模板语法,转义(自动转义,不转义)
7. [用tornado做网站(5)](./307.md)==>模板继承和块语句,CSS文件,cookie以及XSRF安全防护方法

##第五部分:科学计算

##附:网络文摘

1. [如何成为python高手](./n001.md)
2. [ASCII、Unicode、GBK和UTF-8字符编码的区别联系](./n002.md)
1 change: 1 addition & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
5. [用tornado做网站(3)](./305.md)==>ajax传输数据,get_argument()接收数据,验证用户名和密码
6. [用tornado做网站(4)](./306.md)==>render()方法使用,模板语法,转义(自动转义,不转义)
7. [用tornado做网站(5)](./307.md)==>模板继承和块语句,CSS文件,cookie以及XSRF安全防护方法
8. [用tornado做网站(6)](./308.md)==>用户验证

##第五部分:科学计算

Expand Down

0 comments on commit d20c79c

Please sign in to comment.