tornado项目

摘要:
tornado项目之基于领域驱动模型架构设计的京东用户管理后台本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。

tornado项目之基于领域驱动模型架构设计的京东用户管理后台

本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。

一、预备知识:

1.接口:

python中并没有类似java等其它语言中的接口类型,但是python中有抽象类和抽象方法。如果一个抽象类有抽象方法,那么继承它的子类必须实现抽象类的所有方法,因此,我们基于python的抽象类和抽象方法实现接口功能。

示例代码:

接口示例代码

2.依赖注入:

依赖注入的作用是将一系列无关的类通过注入参数的方式实现关联,例如将类A的对象作为参数注入给类B,那么当调用类B的时候,类A会首先被实例化。

示例代码:

依赖注入示例

注:原理:首先需要明确一切事物皆对象类也是对象,类是有Type创建的,当类实例化的时候,会调用type类的call方法,call方法会调用new方法,new方法调用init方法。

二、企业级应用设计

1.总体框架目录结构:

tornado项目第1张

备注:

  • Infrastructure:一些公共组件,例如md5加密,分页模块,session等。
  • Model :关于数据库的逻辑处理模块
  • Repository :数据访问层,包含数据库的增删改查
  • Service :服务层,调用Model,包含带有规则的请求和返回
  • Statics:静态文件目录
  • UI层:业务处理
  • Views:模板文件
  • Application:tornado程序的起始文件
  • Config:配置文件
  • Mapper:依赖注入文件,负责整个框架不同类的依赖注入

2.首先我们从Moldel开始查看:

文件目录:

tornado项目第2张

本文主要以用户管理为例进行介绍,因此我们来关注一下User.py文件:

代码结构:

tornado项目第3张

下面对上述代码结构做一一介绍:

IUseRepository类:接口类,用于约束数据库访问类的方法
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
classIUseRepository:
"""
用户信息仓库接口
"""
deffetch_one_by_user_pwd(self, username, password):
"""
根据用户名密码获取模型对象
:param username: 主键ID
:param password: 主键ID
:return:
"""
deffetch_one_by_email_pwd(self, email, password):
"""
根据邮箱密码获取模型对象
:param email: 主键ID
:param password: 主键ID
:return:
"""
defupdate_last_login_by_nid(self,nid,current_date):
"""
根据ID更新最新登陆时间
:param nid:
:return:
"""

从上述代码可以看出,数据库访问类如果继承IUseRepository类,就必须实现其中的抽象方法。

接下来的三个类,VipType、UserType、User是与用户信息相关的类,是数据库需要保存的数据,我们希望存入数据库的数据格式为:nid 、username、email、last_login、user_type_id、vip_type_id,其中User类用于保存上述数据。因为user_type_id、vip_type_id存的是数字,即user_type_id、vip_type_id是外键,不能直接在前端进行展示,因此,我们创建了VipType、UserType类,用于根据id,获取对应的VIP级别和用户类型。

示例代码:

User类
UserType类
VipType类

注:VipType、UserType这两个类获取对应的caption均是通过类的普通特性访问,即类似字段方式访问。

接下来的类UserService是本py文件的重中之重,它负责调用对应的数据库访问类的方法,并被服务层service调用,具有承上启下的作用:

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
classUserService:
def__init__(self, user_repository):
self.userRepository=user_repository
defcheck_login(self, username=None, email=None, password=None):
ifusername:
user_model=self.userRepository.fetch_one_by_user_pwd(username, password)
else:
user_model=self.userRepository.fetch_one_by_email_pwd(email, password)
ifuser_model:
current_date=datetime.datetime.now()
self.userRepository.update_last_login_by_nid(user_model.nid, current_date)
returnuser_model

这里,我们重点介绍一下上述代码:

初始化参数user_repository:通过依赖注入对应的数据库访问类的对象;

check_login:访问数据库的关键逻辑处理方法,根据用户是用户名+密码方式还是邮箱加密码的方式登录,然后调用对应的数据库处理方法,如果登陆成功,更新时间和最后登录时间,最后将User类的实例返回给调用它的服务层service。(详细见下文数据库处理类的方法)

我们先来看一下对应的数据库处理类中的一个方法:

1
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
deffetch_one_by_user_pwd(self, username, password):
ret=None
cursor=self.db_conn.connect()
sql="""select nid,username,email,last_login,vip,user_type from UserInfo where username=%s and password=%s"""
cursor.execute(sql, (username, password))
db_result=cursor.fetchone()
self.db_conn.close()
ifdb_result:
ret=User(nid=db_result['nid'],
username=db_result['username'],
email=db_result['email'],
last_login=db_result['last_login'],
user_type=UserType(nid=db_result['user_type']),
vip_type=VipType(nid=db_result['vip'])
)
returnret

这里我们使用pymysql进行数据库操作,以用户名+密码登陆为例,如果数据库有对应的用户名和密码,将查询结果放在User类中进行初始化,至此,ret中封装了用户的全部基本信息,将ret返回给上面的check_login方法,即对应上文中的返回值user_model,user_model返回给调用它的服务层service。

总结:Molde最终将封装了用户基本信息的User类的实例返回给服务层service。

3.接下来我们看一下服务层service:

service也是一个承上启下的作用,它调用Moldel文件对应的数据库业务协调方法,并被对应的UI层调用(本例中是UIadmin)。

目录结构:

tornado项目第4张

同样的,我们只介绍User文件夹:它包含4个py文件:

  • ModelView:用于用户前端展示的数据格式化,重点对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
  • Request:封装请求Moldel文件对应数据库协调类的参数
  • Response:封装需要返回UI层的参数
  • Sevice:核心服务处理文件

下面对上述目录做详细代码:

ModelView:

1
2
3
4
5
6
7
8
9
10
11
classUserModelView:
def__init__(self, nid, username, email, last_login, user_type_id, user_type_caption, vip_type_id, vip_type_caption):
self.nid=nid
self.username=username
self.email=email
self.last_login=last_login
self.user_type=user_type_id
self.user_type_caption=user_type_caption
self.vip_type=vip_type_id
self.vip_type_caption=vip_type_caption

注:对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。

Request:

1
2
3
4
5
6
classUserRequest:
def__init__(self, username, email, password):
self.username=username
self.email=email
self.password=password

Response:

1
2
3
4
5
6
classUserResponse:
def__init__(self, status=True, message='', model_view=None):
self.status=status# 是否登陆成功的状态
self.message=message#错误信息
self.modelView=model_view#登陆成功后的用户数据 
UserService:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
classUserService:
def__init__(self, model_user_service):#通过依赖注入Moldel对应的数据库业务协调方法,此例中对应上文中的user_service
self.modelUserService=model_user_service
defcheck_login(self, user_request):#核心服务层业务处理方法
response=UserResponse()#实例化返回类
try:
model=self.modelUserService.check_login(user_request.username, user_request.email, user_request.password)#接收上文中的用户基本信息,是User类的实例
ifnotmodel:
raiseException('用户名或密码错误')
else:#如果登陆成功,通过UserModelView类格式化返回前端的数据
model_view=UserModelView(nid=model['nid'],
username=model['usename'],
email=model['email'],
last_login=model['last_login'],
user_type_id=model['user_type'].nid,
user_type_caption=model['user_type'].caption,
vip_type_id=model['vip_type'].nid,
vip_type_caption=model['vip_type'].caption,)
response.modelView=model_view#定义返回UI层的用户信息
exceptException as e:
response.status=False
response.message=str(e)

总结:至此,Service返回给Ui层的数据是是否登陆成功的状态status、错误信息、已经格式化的用户基本信息。

4.UI层

UI层主要负责业务处理完成后与前端的交互,它是服务层Service的调用者:

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
classLogin(AdminRequestHandler):
defget(self,*args,**kwargs):
is_login=self.session["is_login"]
current_user=""
ifis_login:
current_user=self.session["user_info"].username
self.render('Account/Login.html',current_user=current_user)
defpost(self,*args,**kwargs):
user_request=[]
#获取用户输入的用户名邮箱密码
user_request.append(self.get_argument('name',None))
user_request.append(self.get_argument('email',None))
user_request.append(self.get_argument('pwd',None))
checkcode=self.get_argument("checkcode",None)
Mapper.mapper(*user_request)
obj=UserService.check_login()
self.session["is_login"]=True
self.session["user_info"]=obj.modelView
self.write("已登陆")

总结以上就是基于领域驱动模型的用户管理后台,包含数据库操作文件,数据库业务处理文件,服务端文件,UI层文件。如果本文对您有参考价值

tornado源码系列

tornado项目之基于领域驱动模型架构设计的京东用户管理后台
摘要: 本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。 一、预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中有抽象类和抽象方法。如果一个抽象类有抽象方法,那么继承它的子类必须实现抽象类的所有方法,因此,我们基阅读全文

posted @2016-09-07 09:15战神王恒 阅读(506) |评论 (7)编辑

tornado高效开发必备之源码详解
摘要: 前言:本博文重在tornado源码剖析,相信读者读完此文能够更加深入的了解tornado的运行机制,从而更加高效的使用tornado框架。 本文参考武sir博客地址:http://www.cnblogs.com/wupeiqi/tag/Tornado/ 初识tornado 首先我们从经典的hello阅读全文

posted @2016-09-01 09:10战神王恒 阅读(945) |评论 (22)编辑

tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片
摘要: 本博文将一步步带领你实现抽屉官网的各种功能:包括登陆、注册、发送邮箱验证码、登陆验证码、页面登陆验证、发布文章、上传图片、form验证、点赞、评论、文章分页处理以及基于tornado的后端和ajax的前端数据处理。 转载请注明出处http://www.cnblogs.com/wanghzh/p/58阅读全文

posted @2016-08-29 09:17战神王恒 阅读(1072) |评论 (18)编辑

Web框架之Tornado
摘要: 概述 Tornado是FriendFeed使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py或者Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。 Tornado阅读全文

posted @2016-08-25 18:41战神王恒 阅读(91) |评论 (0)编辑

本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”。

一、预备知识:

1.接口:

python中并没有类似java等其它语言中的接口类型,但是python中有抽象类和抽象方法。如果一个抽象类有抽象方法,那么继承它的子类必须实现抽象类的所有方法,因此,我们基于python的抽象类和抽象方法实现接口功能。

示例代码:

接口示例代码

2.依赖注入:

依赖注入的作用是将一系列无关的类通过注入参数的方式实现关联,例如将类A的对象作为参数注入给类B,那么当调用类B的时候,类A会首先被实例化。

示例代码:

依赖注入示例

注:原理:首先需要明确一切事物皆对象类也是对象,类是有Type创建的,当类实例化的时候,会调用type类的call方法,call方法会调用new方法,new方法调用init方法。

二、企业级应用设计

1.总体框架目录结构:

tornado项目第1张

备注:

  • Infrastructure:一些公共组件,例如md5加密,分页模块,session等。
  • Model :关于数据库的逻辑处理模块
  • Repository :数据访问层,包含数据库的增删改查
  • Service :服务层,调用Model,包含带有规则的请求和返回
  • Statics:静态文件目录
  • UI层:业务处理
  • Views:模板文件
  • Application:tornado程序的起始文件
  • Config:配置文件
  • Mapper:依赖注入文件,负责整个框架不同类的依赖注入

2.首先我们从Moldel开始查看:

文件目录:

tornado项目第2张

本文主要以用户管理为例进行介绍,因此我们来关注一下User.py文件:

代码结构:

tornado项目第3张

下面对上述代码结构做一一介绍:

IUseRepository类:接口类,用于约束数据库访问类的方法
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
classIUseRepository:
"""
用户信息仓库接口
"""
deffetch_one_by_user_pwd(self, username, password):
"""
根据用户名密码获取模型对象
:param username: 主键ID
:param password: 主键ID
:return:
"""
deffetch_one_by_email_pwd(self, email, password):
"""
根据邮箱密码获取模型对象
:param email: 主键ID
:param password: 主键ID
:return:
"""
defupdate_last_login_by_nid(self,nid,current_date):
"""
根据ID更新最新登陆时间
:param nid:
:return:
"""

从上述代码可以看出,数据库访问类如果继承IUseRepository类,就必须实现其中的抽象方法。

接下来的三个类,VipType、UserType、User是与用户信息相关的类,是数据库需要保存的数据,我们希望存入数据库的数据格式为:nid 、username、email、last_login、user_type_id、vip_type_id,其中User类用于保存上述数据。因为user_type_id、vip_type_id存的是数字,即user_type_id、vip_type_id是外键,不能直接在前端进行展示,因此,我们创建了VipType、UserType类,用于根据id,获取对应的VIP级别和用户类型。

示例代码:

User类
UserType类
VipType类

注:VipType、UserType这两个类获取对应的caption均是通过类的普通特性访问,即类似字段方式访问。

接下来的类UserService是本py文件的重中之重,它负责调用对应的数据库访问类的方法,并被服务层service调用,具有承上启下的作用:

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
classUserService:
def__init__(self, user_repository):
self.userRepository=user_repository
defcheck_login(self, username=None, email=None, password=None):
ifusername:
user_model=self.userRepository.fetch_one_by_user_pwd(username, password)
else:
user_model=self.userRepository.fetch_one_by_email_pwd(email, password)
ifuser_model:
current_date=datetime.datetime.now()
self.userRepository.update_last_login_by_nid(user_model.nid, current_date)
returnuser_model

这里,我们重点介绍一下上述代码:

初始化参数user_repository:通过依赖注入对应的数据库访问类的对象;

check_login:访问数据库的关键逻辑处理方法,根据用户是用户名+密码方式还是邮箱加密码的方式登录,然后调用对应的数据库处理方法,如果登陆成功,更新时间和最后登录时间,最后将User类的实例返回给调用它的服务层service。(详细见下文数据库处理类的方法)

我们先来看一下对应的数据库处理类中的一个方法:

1
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
deffetch_one_by_user_pwd(self, username, password):
ret=None
cursor=self.db_conn.connect()
sql="""select nid,username,email,last_login,vip,user_type from UserInfo where username=%s and password=%s"""
cursor.execute(sql, (username, password))
db_result=cursor.fetchone()
self.db_conn.close()
ifdb_result:
ret=User(nid=db_result['nid'],
username=db_result['username'],
email=db_result['email'],
last_login=db_result['last_login'],
user_type=UserType(nid=db_result['user_type']),
vip_type=VipType(nid=db_result['vip'])
)
returnret

这里我们使用pymysql进行数据库操作,以用户名+密码登陆为例,如果数据库有对应的用户名和密码,将查询结果放在User类中进行初始化,至此,ret中封装了用户的全部基本信息,将ret返回给上面的check_login方法,即对应上文中的返回值user_model,user_model返回给调用它的服务层service。

总结:Molde最终将封装了用户基本信息的User类的实例返回给服务层service。

3.接下来我们看一下服务层service:

service也是一个承上启下的作用,它调用Moldel文件对应的数据库业务协调方法,并被对应的UI层调用(本例中是UIadmin)。

目录结构:

tornado项目第4张

同样的,我们只介绍User文件夹:它包含4个py文件:

  • ModelView:用于用户前端展示的数据格式化,重点对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。
  • Request:封装请求Moldel文件对应数据库协调类的参数
  • Response:封装需要返回UI层的参数
  • Sevice:核心服务处理文件

下面对上述目录做详细代码:

ModelView:

1
2
3
4
5
6
7
8
9
10
11
classUserModelView:
def__init__(self, nid, username, email, last_login, user_type_id, user_type_caption, vip_type_id, vip_type_caption):
self.nid=nid
self.username=username
self.email=email
self.last_login=last_login
self.user_type=user_type_id
self.user_type_caption=user_type_caption
self.vip_type=vip_type_id
self.vip_type_caption=vip_type_caption

注:对user_type_id、vip_type_id增加对应的用户类型和VIP级别,即将外键数据对应的caption放在外键后面,作为增加的参数。

Request:

1
2
3
4
5
6
classUserRequest:
def__init__(self, username, email, password):
self.username=username
self.email=email
self.password=password

Response:

1
2
3
4
5
6
classUserResponse:
def__init__(self, status=True, message='', model_view=None):
self.status=status# 是否登陆成功的状态
self.message=message#错误信息
self.modelView=model_view#登陆成功后的用户数据 
UserService:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
classUserService:
def__init__(self, model_user_service):#通过依赖注入Moldel对应的数据库业务协调方法,此例中对应上文中的user_service
self.modelUserService=model_user_service
defcheck_login(self, user_request):#核心服务层业务处理方法
response=UserResponse()#实例化返回类
try:
model=self.modelUserService.check_login(user_request.username, user_request.email, user_request.password)#接收上文中的用户基本信息,是User类的实例
ifnotmodel:
raiseException('用户名或密码错误')
else:#如果登陆成功,通过UserModelView类格式化返回前端的数据
model_view=UserModelView(nid=model['nid'],
username=model['usename'],
email=model['email'],
last_login=model['last_login'],
user_type_id=model['user_type'].nid,
user_type_caption=model['user_type'].caption,
vip_type_id=model['vip_type'].nid,
vip_type_caption=model['vip_type'].caption,)
response.modelView=model_view#定义返回UI层的用户信息
exceptException as e:
response.status=False
response.message=str(e)

总结:至此,Service返回给Ui层的数据是是否登陆成功的状态status、错误信息、已经格式化的用户基本信息。

4.UI层

UI层主要负责业务处理完成后与前端的交互,它是服务层Service的调用者:

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
classLogin(AdminRequestHandler):
defget(self,*args,**kwargs):
is_login=self.session["is_login"]
current_user=""
ifis_login:
current_user=self.session["user_info"].username
self.render('Account/Login.html',current_user=current_user)
defpost(self,*args,**kwargs):
user_request=[]
#获取用户输入的用户名邮箱密码
user_request.append(self.get_argument('name',None))
user_request.append(self.get_argument('email',None))
user_request.append(self.get_argument('pwd',None))
checkcode=self.get_argument("checkcode",None)
Mapper.mapper(*user_request)
obj=UserService.check_login()
self.session["is_login"]=True
self.session["user_info"]=obj.modelView
self.write("已登陆")

总结以上就是基于领域驱动模型的用户管理后台,包含数据库操作文件,数据库业务处理文件,服务端文件,UI层文件。如果本文对您有参考价值

免责声明:文章转载自《tornado项目》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇中文前端UI框架Kit(十三)使用RequireJs托管你的类库和js代码java 关于JDBC和DAO模式使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

LINQ篇:查询句法

查询句法是使用标准的LINQ查询运算符来表达查询时一个方便的声明式简化写法。该句法能在代码里表达查询时增进可读性和简洁性,读起来容易,也容易让人写对。Visual Studio 对查询句法提供了完整的intellisense和编译时检查支持。 在底下,C#和VB编译器则把查询句法的表达式翻译成明确的方法调用代码,这样的代码利用了Orcas中的新的扩展方法和...

[SQL Server] 数据库日志文件自动增长导致连接超时的分析

1、现象、问题描述 客户反映某客户端登陆不了,客户端程序日志显示“连接数据库超时”;检查对应的数据库服务器,日志显示“Autogrow of file '某数据库日志文件' in database '某数据库' was cancelled by user or timed out after 2391 milliseconds. Use ALTER DAT...

7 款顶级的开源 Web 分析软件

Web 分析无非就是 Web 流量的测量。但它并不限于测量网络流量,还包括: 分析 数据采集 为了了解和优化网页而上报网络数据 Google Analytics是最广泛使用的基于云的网络分析服务。不过,你的数据已被锁定在Google的生态系统中。如果你想要100%的数据拥有权,请尝试以下开源网络分析软件来获取有关网站的访问者数量和页面浏览量的信息。...

oracle 中的truncate 和delete

一、查询表大小,块多少语句 Select SEGMENT_Name,BYTES,BLOCKS,Extents From dba_segments Where segment_name In('BAI_NEW_SESSION_HISTORY2') order by segment_name; (2)查表空间 Select Tablespace_Name,...

Redis的高可用:哨兵和集群

Redis的高可用:哨兵和集群 人邮异步社区 官方微信:异步社区,人民邮电出版社旗下IT专业图书旗舰社区 已关注 26 人赞同了该文章 我们在讨论分布式系统的时候,曾经谈过分布式系统要解决的是高并发、大数量和快速响应的问题。事实上,在互联网中,大部分的业务还是以查询数据为主,而非更改数据为主。在互联网出现高并发的时刻,查询关系数据库,会造成...

数据库的日志

数据库都具有事务日志,用于记录所有事务以及每个事务对数据库所做的修改。事务日志是数据库的重要组件,如果系统出现故障,则可能需要使用事务日志将数据库恢复到一致状态。删除或移动事务日志以前,必须完全了解此操作带来的后果。事务日志支持以下操作:    恢复个别的事务。    在 SQL Server 启动时恢复所有未完成的事务。    将还原的数据库、文件、文件...