在上一篇博客中,我为大家介绍了angular调用服务的原理,以及实现了用户登录功能的前端部分。在这期博客中,我们将继续实现用户登录的后端部分,以及介绍angular的路由事件。
十 用户登录功能的开发
2 后端部分
我们打开util/users/userutil.py文件,实现loginuser函数:
# util/users/userutil.py
def loginuser(username,password):
password = encryption(password)
user = session.query(User).filter(and_(User.username == username,User.password == password)).first()
result = 'Fail'
if type(user) is User:
user.lastlogintime = datetime.now()
result = insertdata(user)
return result
这个函数很简单,用之前我们实现的加密函数把传入的密码进行加密,然后配合用户名去数据库中查找用户,如果找到了,则更新user表的lastlogintime字段;如果没找到,则返回Fail。
再打开apps/user_app/user_app.py,实现Login的RequestHandler:
# apps/user_app/user_app.py
class Login(BaseHandler):
def post(self):
ret = self.request.body
req = json_decode(ret)
username = req['username']
password = req['password']
result = loginuser(username,password)
returnResult = {'result': result}
returnResult_str = json.dumps(returnResult)
self.write(returnResult_str)
Login只实现post方法,从前端读入用户名和密码后,传入loginuser函数中登录用户,并将结果返回给前端。
最后,在main.py中注册Login的路由:
def make_app():
routelist = [
# ...
(r"/login",Login),
]
return tornado.web.Application(routelist,cookie_secret='12f6352#527',autoreload=True,debug=True,template_path='D:\\LeaveManage\\server\\template')
这样,我们用户登录的后端部分就实现了。
3 angular的路由事件
让我们再次把目光回到前端部分。我们在这个系列的第三篇中实现了主页面组件mainlayout,当时我们在前端模板中定义了一个名为isLogin的变量,并将其初始化为False。现在,我们已经实现了用户登录功能,就可以利用这个变量来检查用户登录与否了。
我们打开mainlayout.component.ts,修改mainlayout的构造函数,以及编写checkLogin函数用于检查用户是否登录:
//mainlayout.component.ts
import { Router, NavigationEnd } from '@angular/router';
//...
constructor(private cookie:CookieService,private router:Router) {
this.isLogin = false;
this.currentUser = this.cookie.get('currentuser')
this.router.events.subscribe(event =>{
if (event instanceof NavigationEnd)
{
this.checkLogin();
}
})
}
checkLogin():void{
if (this.cookie.get('currentuser')){
this.isLogin = true;
}
else{
this.isLogin = false;
}
}
//...
与之前的构造函数相比,我们这次在构造函数里添加了一个CookieService的对象和一个Router对象。前者用于判断当前页面是否存在cookie,而后者则是用来触发各种路由事件的。
路由事件是指当访问路由的过程中所触发的事件。通过路由事件,我们可以指定当页面开始加载、结束加载等时刻的行为,或者干脆限制用户访问某个路由所指向的位置。在这里,我们使用路由事件来判断用户是否登录,一旦用户成功登录并重定向到主页时,我们需要实时获得用户已经登录的信息,并显示登录后的菜单项。
在构造函数中,我们首先会从名为currentuser的cookie中获得当前登录的用户名,接下来会监听NavigationEnd路由事件,这个路由事件的触发时机为页面完全加载完成后。我们在这个路由事件中会调用checkLogin函数,这个函数会根据是否存在currentuser这个cookie而改变isLogin的值。如果存在名为currentuser的cookie,则将isLogin设为true;反之设为false。
最后,在ngOnInit函数中同样调用checkLogin函数:
// mainlayout.component.ts
ngOnInit() {
this.checkLogin()
console.log(this.isLogin)
}
4 退出登录与事件绑定
既然我们已经实现了用户登录,那么自然也要实现退出登录。退出登录没有任何后端代码,因为我们只需把那个currentuser的cookie删除掉,并修改isLogin为false就可表示当前用户已经退出了。我们在mainlayout.component.ts中实现logoutUser函数,用于退出登录:
//mainlayout.component.ts
logoutUser()
{
console.log('Logout user')
this.cookie.delete('currentuser','/','localhost',true,"Lax")
this.isLogin = false
}
然后,回到mainlayout.component.html文件中,给菜单项中的退出添加一个绑定,将这个菜单项绑定到logoutUser函数上:
<!-- mainlayout.component.html-->
<nz-dropdown-menu #menu="nzDropdownMenu" >
<ul nz-menu nzSelectable>
<li nz-menu-item>书写故事</li>
<li nz-menu-item>个人信息</li>
<li nz-menu-item (click)="logoutUser()">退出</li>
</ul>
</nz-dropdown-menu>
这里使用angular的事件绑定语法来将click这个事件与logoutUser函数进行绑定,即当单击这个菜单项时,会触发logoutUser函数。通过事件绑定,我们可以对用户的操作进行响应,如按下键盘、鼠标移动等。angular提供的绑定语法如下:
click是事件名,onSave()是函数名。当click事件发生时,就会调用onSave函数。
这样,当我们点击退出菜单项时,就会调用logoutUser函数将cookie删除,并将isLogin设为false,从而实现用户退出的操作。
在这期博客中,我们实现了用户登录功能的后端部分,以及顺便实现了用户退出功能。目前,我们的博客已经有了一个最基本的用户系统。在下一篇博客中,我们将开始开发我们的核心部分——故事系统和评论系统,希望大家继续关注~