GO语言开发天天生鲜项目第三天 用户模块开发
项目分析
一.项目架构
二.数据库表设计
用户模块
##一.用户注册
用户通过我们的网站购买商品前,必须要登录。如果,该用户在我们的网站上没有账号,那么必须进行注册。下面我们看一下注册的具体实现过程(注意:这里讲解的时候,一定先演示效果,然后分析步骤)
###1.前端处理
从前端设计人员获取注册的前端页面后,我们首先要呈现出来,这样需要在user.go文件中,创建一个方法,负责指定前端的注册页面。这个方法为ShowReg( ),该方法的具体实现如下:
func (this*UserController)ShowReg(){
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
}
下面,我们看一下前端的注册页面内容:
在该注册页面中,包含了用户注册时需要填写的信息,例如:用户名,密码,密码确认,邮箱信息。
在这里,大家需要注意的是,为了保证用户填写信息的准确性,在这里需要对用户填写的信息进行校验。关于表单的校验,这里我们需要用到大家前面学习的Jquery,所以这里需要在标签中引入jquery文件:
关于具体校验的实现,前端人员也已经封装在了一个js文件中了,该文件为:register.js
所以也需要将该文件在标签中引入一下:
下面,我们来看一下,register.js文件的具体实现如下:
$(function(){
//定义变量,默认值为false。
var error_name = false;//如果用户名出现了错误,将该变量的值修改为true.
var error_password = false;//如果密码出现了错误,将该变量的值修改为true.
var error_check_password = false;//如果密码确认出现了错误,该变量的值修改为true.
var error_email = false;//如果邮箱出现了错误,该变量的值修改为true.
var error_check = false;//如果选择同意协议,该变量的值修改为true.
//根据id的值,找到“user_name”,并且绑定一个blur事件,也就是当该文本框失去焦点后,执行其对应的方法。
$('#user_name').blur(function() {
check_user_name();
});
//同上
$('#pwd').blur(function() {
check_pwd();
});
//同上
$('#cpwd').blur(function() {
check_cpwd();
});
//同上
$('#email').blur(function() {
check_email();
});
//根据id找到“allow”,并且绑定一个单击事件,并且判断该元素是否被选中,
//如果选中了,将变量 error_check变量的值修改为false,并且将其同胞元素隐藏、
//如果没有选中,将变量error_check变量的值修改为true,并且在其同胞元素上打印“请勾选同意”
//并且将该标签显示出来。
$('#allow').click(function() {
if($(this).is(':checked'))
{
error_check = false;
$(this).siblings('span').hide();
}
else
{
error_check = true;
$(this).siblings('span').html('请勾选同意');
$(this).siblings('span').show();
}
});
//获取用户名的长度,并且进行判断其长度,如果不符合条件,显示出对应的错误提示。
function check_user_name(){
var len = $('#user_name').val().length;
if(len<5||len>20)
{
$('#user_name').next().html('请输入5-20个字符的用户名')
$('#user_name').next().show();
error_name = true;
}
else
{
$('#user_name').next().hide();
error_name = false;
}
}
//获取密码的长度,并且进行长度的判断,如果不符合条件,显示出对应的错误提示
function check_pwd(){
var len = $('#pwd').val().length;
if(len<8||len>20)
{
$('#pwd').next().html('密码最少8位,最长20位')
$('#pwd').next().show();
error_password = true;
}
else
{
$('#pwd').next().hide();
error_password = false;
}
}
//密码确认判断,获取密码框中输入的内容,同时获取“确认密码框”中输入的内容,进行比较。
//如果两个值相等,表示两次输入的密码一致,否则给出错误提示。
function check_cpwd(){
var pass = $('#pwd').val();
var cpass = $('#cpwd').val();
if(pass!=cpass)
{
$('#cpwd').next().html('两次输入的密码不一致')
$('#cpwd').next().show();
error_check_password = true;
}
else
{
$('#cpwd').next().hide();
error_check_password = false;
}
}
//对邮箱格式进行校验,判断其输入的邮箱是否符合对应的格式,如果不符合,给出对应的错误提示。
//这里对邮箱格式的校验,使用了正则表达式。
function check_email(){
var re = /^[a-z0-9][w.-]*@[a-z0-9-]+(.[a-z]{2,5}){1,2}$/;
if(re.test($('#email').val()))
{
$('#email').next().hide();
error_email = false;
}
else
{
$('#email').next().html('你输入的邮箱格式不正确')
$('#email').next().show();
error_check_password = true;
}
}
//当用户单击“注册”按钮时,在将数据发送服务端之前,会先调用submit方法,
//在该方法中,会将上面所有校验的方法进行调用,然后判断其对应的变量的值
//如果所有变量的值为false,表示校验全部通过,那么会将表单中的数据发送到服务端,否则是不会发送到服务端的。
//注意:reg_from为form标签的id属性的值,当单击“注册”这个submit按钮时,会先执行submit方法。
//只有该方法最终返回的结果为true,才会将数据发送到服务端。
$('#reg_form').submit(function() {
//调用上面校验的方法。
check_user_name();
check_pwd();
check_cpwd();
check_email();
//判断其变量的值,如果全部为false,表示校验全部通过,这时submit方法最终会返回true,
//这时,才会将表单中的数据发送到服务端。如果submit方法最终返回的是false,就不会向服务端提交发送数据。
if(error_name == false && error_password == false && error_check_password == false && error_email == false && error_check == false)
{
return true;
}
else
{
return false;
}
});
})
###2.服务器端处理
如果,客户端校验全部成功了,就会将用户在表单中输入的数据发送到服务端。
那么,接下来我们看一下,服务端是怎样对发送过来的数据进行处理的?
####2.1:关于标签的设置
在前面的课程学习过程中,我们大家都知道,要将前端表单中的数据发送到服务端,必须给标签指定两个很重要的属性,一个是是method,一个是action,这里我们给这两个属性,指定如下两个值。
{{.errmsg}}
2.2.4:完成信息的保存
如果校验完用户名,发现没有重名的情况,那么可以将用户的信息存储到数据库中,具体实现的代码如下:
_,err = o.Insert(&user)
if err != nil {
this.Data["errmsg"] = "插入失败,请重新注册!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
2.2.4:发送邮件
将用户的信息,存储到数据库中以后,接下来可以给用户发送一封邮件,并且告诉用户只有去邮箱中激活以后,才能进行登录。
给用户发送邮件一个很重要的好处就是,可以判断用户在注册时输入的邮箱是否正确。
只有正确地用户邮箱,才有意义,例如:当我们的网站上架一款新产品时,可以给注册的用户发送邮件,通知其新上架的产品信息。
具体实现的过程如下:
SMTP服务器就是邮件代收发服务器,由邮件服务商提供,常见的SMTP服务器端口号:
QQ邮箱:SMTP服务器地址:smtp.qq.com(端口:587)
雅虎邮箱: SMTP服务器地址:smtp.yahoo.com(端口:587)
163邮箱:SMTP服务器地址:smtp.163.com(端口:25)
126邮箱: SMTP服务器地址:smtp.126.com(端口:25)
新浪邮箱: SMTP服务器地址:smtp.sina.com(端口:25)
要能够发送邮件首先要进行邮箱的配置,配置过程如下:
具体实现步骤如下:
第一:指定发送邮件的配置信息。
config := `{"username":"563364657@qq.com","password":"kufzjehabgesbceb","host":"smtp.qq.com","port":587}`
这里指定了发件人的邮箱名称,对应的发送密码,对应SMTP服务器,以及对应的端口号。
这里我们使用的是QQ的邮箱,所以SMTP服务器指的是QQ的SMTP服务器地址,如果发件人使用的是163的邮箱,这里需要指定的163的SMTP服务器地址:smtp.163.com
第二:根据配置信息,创建一个EMAIL的对象
temail:=utils.NewEMail(config)
第三:通过EMAIL对象中的属性。指定,发件人邮箱,收件人邮箱,邮件标题,以及邮件的内容。
temail.To = []string{user.Email}//指定收件人邮箱地址,就是用户在注册时填写的邮箱地址
temail.From = "563364657@qq.com"//指定发件人的邮箱地址,这里我们使用的QQ邮箱。
temail.Subject = "天天生鲜用户激活"//指定邮件的标题
//指定邮件的内容。该内容发送到用户的邮箱中以后,该用户打开邮箱,可以将该URL地址复制到地址栏中,敲回车键,就会向该指定的URL地址发送请求,我们在该地址对应的方法中,接收该用户的ID,然后根据该Id,查询出用户的信息后,将其对应的一个属性,Active设置为true,表明用户已经激活了,那么用户就可以登录了。
temail.HTML = "复制该连接到浏览器中激活:127.0.0.1:8088/active?id="+strconv.Itoa(user.Id)
第四:发送邮件
调用EMAIL对象中的send方法发送邮件,如果邮件发送失败,给用户相应的提示并且重新返回到注册页面,让用户填写相应的信息,如果邮件发送成功,也要给出相应的提示。
err = temail.Send()
if err != nil{
this.Data["errmsg"] = "发送激活邮件失败,请重新注册!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
this.Ctx.WriteString("注册成功,请前往邮箱激活!")
发送成功后邮箱显示图下
2.2.5:HandleReg方法完整代码
//处理注册业务
func (this*UserController)HandleReg(){
//1.获取数据
userName := this.GetString("user_name")
pwd := this.GetString("pwd")
cpwd := this.GetString("cpwd")
email := this.GetString("email")
//2.数据校验
if userName == "" || pwd == "" || cpwd == "" || email == ""{
this.Data["errmsg"] = "输入信息不完整,请重新输入!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
if pwd != cpwd{
this.Data["errmsg"] = "两次输入密码不一致,请重新输入!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
_,err:=regexp.Compile(email)
if err != nil{
this.Data["errmsg"] = "邮箱格式不正确"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
//3.插入数据库
o := orm.NewOrm()
user := models.User{}
user.Name = userName
user.PassWord = pwd
user.Email = email
//4.判断用户名是否重复,如果重复重新注册
err = o.Read(&user,"Name")
if err != orm.ErrNoRows{
this.Data["errmsg"] = "用户以存在,请重新注册!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
//插入数据库
_,err = o.Insert(&user)
if err != nil {
this.Data["errmsg"] = "插入失败,请重新注册!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
//发送邮件
config := `{"username":"563364657@qq.com","password":"kufzjehabgesbceb","host":"smtp.qq.com","port":587}`
temail:=utils.NewEMail(config)
temail.To = []string{user.Email}
temail.From = "563364657@qq.com"
temail.Subject = "天天生鲜用户激活"
temail.HTML = "复制该连接到浏览器中激活:127.0.0.1:8088/active?id="+strconv.Itoa(user.Id)
err = temail.Send()
if err != nil{
this.Data["errmsg"] = "发送激活邮件失败,请重新注册!"
this.TplName = "https://blog.csdn.net/fegus/article/details/register.html"
return
}
this.Ctx.WriteString("注册成功,请前往邮箱激活!")
}
2.3:邮箱激活
在上面的注册模块中,我们已经将邮件发送到用户的邮箱中了,那么用户登录邮箱以后,将url地址拷贝到地址栏中,敲回车键,就会向我们指定的URL地址发送请求,我们只要根据传递过来的用户Id值,找到该用户并且将对应的Active属性设置为true,就可以了。
具体的实现过程如下:
2.3.1:接收用户编号
id,err:=this.GetInt("id")
if err !=nil{
this.Data["errmsg"] = "激活路径不正确,请重新确定之后登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
接收传递过来过来的id值,并且转成对应的整型,当如如果转换失败,给出相应的错误提示。
2.3.2:获取用户信息
根据接收到的用户的Id值,查询出对应的用户信息。如果没有找到对应的注册用户,给出相应的错误提示。
o:=orm.NewOrm()
user := models.User{Id:id}
err = o.Read(&user)
if err != nil{
this.Data["errmsg"] = "激活路径不正确,请重新确定之后登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
}
2.3.3:修改对应的属性
如果找到了对应的用户信息,将其对应的Active属性值修改为true.最后跳转到登录页面,用户就可以进行登录了。
user.Active = true
_,err = o.Update(&user)
if err != nil{
this.Data["errmsg"] = "激活失败,请重新确定之后登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
}
this.Redirect("/login",302)
2.3.4:完整的用户激活代码
func(this*UserController)ActiveUser(){
//获取传输过来的数据
id,err:=this.GetInt("id")
if err !=nil{
this.Data["errmsg"] = "激活路径不正确,请重新确定之后登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
//更新激活字段
o:=orm.NewOrm()
user := models.User{Id:id}
err = o.Read(&user)
if err != nil{
this.Data["errmsg"] = "激活路径不正确,请重新确定之后登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
}
user.Active = true
_,err = o.Update(&user)
if err != nil{
this.Data["errmsg"] = "激活失败,请重新确定之后登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
}
this.Redirect("/login",302)
}
大家,还要注意路由的配置,这里是get请求。因为用户是将URL地址拷贝到地址栏中,通过地址栏发送请求的。
beego.Router("/active",&controllers.UserController{},"get:ActiveUser")
二:用户登录
前面我们已经完成了用户注册,那么接下来我们要实现的就是用户登录、
1:展示登录页面
在这里首先也是要展示出一个登录页面。
但是在展示登录页面之前,我们需要判断一下一个叫username的cookie中是否有值,该cookie中存储的是用户名,如果有值,表明用户不是第一次登录了,以前该用户登录过。那么我们将从cookie中获取的值通过this.data[“username”]的方式传递到https://blog.csdn.net/fegus/article/details/login.html视图中,然后填充到“用户名文本框”中。并且将一个”checked"字符串也传递到视图中。
func(this*UserController)ShowLogin(){
username:=this.Ctx.GetCookie("username")
if username != ""{
this.Data["username"] = username
this.Data["checked"] = "checked"
}else {
this.Data["username"] = ""
this.Data["checked"] = ""
}
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
}
关于https://blog.csdn.net/fegus/article/details/login.html视图的处理:
在https://blog.csdn.net/fegus/article/details/login.html视图中,我们将从服务端传递过来的用户名填充到了用户名这个文本框中。
并且让“记住用户名”这个文本框处于选中状态。
我们这样做的目的就是,当用户登录了一次后,当下次在来访问登录页面时,可以从cookie中获取该用户名,填充到“用户名文本框”中,不需要在“用户名文本框”中重新输入用户名,方便了用户。
2:服务端处理
前端登录页面处理完成后,当用户单击“登录”按钮后,会将输入的用户名和密码提交到服务端,那么我们服务端应该怎样进行处理呢?
首先我们看到表单中,method的取值为“post",action的取值为”/login“,对应的路由如下:
beego.Router("/login",&controllers.UserController{},"get:ShowLogin;post:HandleLogin")
通过该路由,我们知道当用户向“/login”发送"get"请求时,会访问我们上面定义的“ShowLogin”方法,如果发送的是“post”请求,那么会访问“HandleLogin”方法,那么接下来我们要做的就是在该方法中,完成对用户名和密码的校验,如果都输入正确,完成用户的登录。如果某一项输入错误,要让用户重新的输入。
2.1:接收用户名和密码
接收用户名和密码以及接受“记住用户名”复选框的值,并且判断用户名和密码是否为空,如果为空给出相应的错误提示。
userName := this.GetString("username")
pwd := this.GetString("pwd")
check := this.GetString("check")
if userName==""||pwd == ""{
this.Data["errmsg"] = "用户名或密码不能为空,请重新登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
2.2:校验用户名密码
如果用户名和密码不为空,那么接下来我们要判断的就是用户名和密码是否正确。判断的方式,就是根据用户输入的用户名和密码与数据库中存储的用户名和密码进行比较,如果相同那么表示输入正确,否则为输入错误。
2.2.1:首先判断用户名是否正确
o:=orm.NewOrm()
user := models.User{Name:userName}
err:=o.Read(&user,"Name")
if err !=nil{
this.Data["errmsg"] = "用户名或密码错误,请重新登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
根据接收到的用户名,创建一个user对象,然后通过orm框架中Read( )方法查询“Name"这个列,也就是看一下数据库中是否存在用户输入的用户名,如果没有给出错误提示,重新展示”登录“页面。
2.2.2:判断密码是否正确
如果密码不正确,也要给出相应的错误提示,并且重新展示“登录”页面。
if user.PassWord != pwd{
this.Data["errmsg"] = "用户名或密码错误,请重新登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
2.2.3:判断用户是否激活。
前面我们在讲解注册时说过,如果用户不激活,我们是不允许用户登录的,所谓用户激活其实就是将其对应的Active属性设置为true.所以这里我们判断一下Active的属性,如果为true,表示用户已经激活了,否则表示用户没有激活。
if user.Active != true{
this.Data["errmsg"] = "该用户没有激活,请县激活!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
2.2.4:完成“记住用户名”
我们在前面接收了“check”这个复选框的值,接下来我们可以判断一下该值,如果该值为"on",表示用户选择了“记住用户名”这个复选框,那么接下来我们可以将用户名存储到cookie中,并且设置相应的过期时间,否则,删除cookie.
if check == "on"{
this.Ctx.SetCookie("username",userName,time.Second * 3600)
}else {
this.Ctx.SetCookie("username",userName,-1)
}
关于设置“记住用户名”的好处,我们前面也已经提到过了,就是将用户名以cookie的形式存储在浏览器端,当用户下次再来访问的时候,浏览器会将该cookie的值发送过来,我们接收该值,然后将其填充到登录页面中的"用户名文本框"中(关于这块代码我们前面已经实现了),这样用户就不需要在输入用户名了,非常方便。
2.2.5:完成Session操作
下面我们实现的就是,将用户名存储到session中。并且完成页面的跳转
this.SetSession("userName",userName)
this.Redirect("/",302)
2.2.6:登录完整代码
func(this*UserController)HandleLogin(){
//1.获取数据
userName := this.GetString("username")
pwd := this.GetString("pwd")
check := this.GetString("check")
if userName==""||pwd == ""{
this.Data["errmsg"] = "用户名或密码不能为空,请重新登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
//2.查询数据
o:=orm.NewOrm()
user := models.User{Name:userName}
err:=o.Read(&user,"Name")
if err !=nil{
this.Data["errmsg"] = "用户名或密码错误,请重新登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
if user.PassWord != pwd{
this.Data["errmsg"] = "用户名或密码错误,请重新登陆!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
if user.Active != true{
this.Data["errmsg"] = "该用户没有激活,请县激活!"
this.TplName = "https://blog.csdn.net/fegus/article/details/login.html"
return
}
if check == "on"{
this.Ctx.SetCookie("username",userName,time.Second * 3600)
}else {
this.Ctx.SetCookie("username",userName,-1)
}
this.SetSession("userName",userName)
this.Redirect("/",302)
}
三:用户退出
用户访问完网站后,可以退出登录。登录的退出非常简单,就是清空session的值。同时完成页面的跳转。
func(this*UserController)Logout(){
this.DelSession("userName")
this.Redirect("/",302)
}
四: 过滤器
接着要实现的界面就是用户登录之后才能访问的界面,所以需要做登陆校验,这里我们通过过滤器函数实现登陆校验:代码如下:
var fifterFunc = func(ctx *context.Context) {
userName := ctx.Input.Session("userName")
if userName == nil{
ctx.Redirect(302,"/login")//如果没有登陆就返回登陆界面
}
}
然后在router文件的init函数中加入一下代码:
beego.InsertFilter("/goods/*",beego.BeforeRouter,fifterFunc)
后面要实现的页面如果是需要登录之后才能访问的,就需要在其对应的路由前加上/goods
五:用户中心
1.个人信息页
在用户登录成功后,我们跳转到了首页,跳转的方式是
this.Redirect("/",302)
这时首页面最上面的信息,发生了改变,如下图所示:
当单击“用户中心”链接时,会跳转到用户中心管理页面,如下图所示:
对应的路由:
beego.Router("https://blog.csdn.net/goods/UserCenterInfo",&controllers.UserController{},"get:ShowCenterInfo")
在用户中心管理页面,可以完成用户的基本信息的管理操作。
ShowCenterInfo方法的实现如下:
1.1:获取登录用户信息
从session中获取登录用户的用户名,因为我们在前面做登录模块时,最后是将用户名存储到了session中。
username := this.GetSession("userName")
//根据用户名获取用户信息
user := GetUser(username.(string))
1.2:获取地址信息
既然我们的需求是展示登录用户的地址信息,所以这里需要查询一下Address表,同时关联了User表。
o:=orm.NewOrm()
var addr models.Address
o.QueryTable("Address").RelatedSel("User").Filter("User__Id",user.Id).Filter("Is_default",true).One(&addr)
1.3:展示数据
this.Data["add"] = addr
this.Data["userName"] = username
this.Layout = "layout.html"
this.TplName = "user_center_site.html"
1.4:个人信息页展示完整代码
username := this.GetSession("userName")//获取session数据
//根据用户名获取用户信息
o := orm.NewOrm()
user := models.User{Name:userName.(string)}
o.Read(&user,"Name")
//获取地址数据
var addr models.Address
o.QueryTable("Address").RelatedSel("User").Filter("User__Id",user.Id).Filter("Is_default",true).One(&addr)
//向视图中传递数据
this.Data["addr"] = addr
this.Data["userName"] = username
this.Layout = "layout.html"
this.TplName = "user_center_info.html"
2.视图布局
通过前面代码的编写,我们发现首页和用户中心-个人信息页的显示很类似,可以用视图布局减少我们代码的书写。
2.1:抽离html界面相同的部分
通过观察我们发现,两个界面的头部和尾部是一样的,所以我们可以把这部分代码抽离出来。创建一个layout.html文件保存这部分代码,layout.html代码如下:
天天生鲜-首页
{{.LayoutContent}}
2.2在相应的界面中删除共同的部分
有了layout.html之后,就可以把https://blog.csdn.net/fegus/article/details/index.html和user_center_info.html相同的部分删掉,然后在渲染相应页面的地方加上如下代码:
展示首页的函数ShowIndex中的代码改为:
userName := this.GetSession("userName")
if userName != nil{
this.Data["userName"] = userName.(string)
}else {
this.Data["userName"] = ""
}
this.Layout = "layout.html"//指定布局页面
this.TplName = "https://blog.csdn.net/fegus/article/details/index.html"//显示主要页面
展示个人信息页的函数ShowCenterInfo中的代码改为:
username := this.GetSession("userName")
//根据用户名获取用户信息
user := GetUser(username.(string))
//获取地址数据
o:=orm.NewOrm()
var addr models.Address
o.QueryTable("Address").RelatedSel("User").Filter("User__Id",user.Id).Filter("Is_default",true).One(&addr)
//向视图中传递数据
this.Data["addr"] = addr
this.Data["userName"] = username
this.Layout = "layout.html"
this.TplName = "user_center_info.html"
3.全部订单页
3.1订单页显示
访问订单页面也是需要登录之后才可以访问,所以我们可以设计他对应的路由如下:
//展示用户订单页面
beego.Router("/goods/UserCenterOrder",&controllers.UserController{},"get:ShowCenterOrder")
设置完路由之后,接着我们实现ShowCenterOrder 函数,因为我们订单模块还没有实现,所以这里我们先只是先把也买你简单的显示出来,等我们订单模块实现之后再处理。这里的页面和首页的样式也类似,所以我们也套用视图布局,代码如下:
username := this.GetSession("userName")
this.Data["userName"] = username
this.Layout = "layout.html"//指定布局页面
this.TplName = "https://blog.csdn.net/fegus/article/details/user_center_order.html"
4.收获地址页面
4.1路由设置
访问地址页面也需要登陆之后才可以,所以我们设计他的路由如下:
//展示用户订单页面beego.Router("/goods/UserCenterSite",&controllers.UserController{},"get:ShowCenterSite;post:HandleCenterSite"
地址页面显示如下:
所以这个页面分两个部分,一个是显示收货地址,一个是提交新的地址。
4.2显示收货地址
4.2.1:获取登录用户信息
我们在前面实现登陆功能的时候是将用户名存储到了session中,所以这里我们获取用户信息可以通过获取session中的用户名,然后查找到用户信息,代码如下:
username := this.GetSession("userName")
//根据用户名获取用户信息
o := orm.NewOrm()
user := models.User{Name:userName}
o.Read(&user,"Name")
4.2.2:获取地址信息
既然我们的需求是展示登陆用户的地址信息,所以这里需要查询一下Address表。查询Address信息,我们可以根据User表,做一个默认地址的过滤,代码如下:
var addr models.Address
o.QueryTable("Address").RelatedSel("User").Filter("User__Id",user.Id).Filter("Is_default",true).One(&addr)
4.2.3:展示默认地址
this.Data["add"] = addr
this.Data["userName"] = username
this.LayOut = "layout.html"//这里我们也套用了视图布局
this.TplName = "user_center_info.html"
4.2.4完整代码
username := this.GetSession("userName")//获取session数据
//根据用户名获取用户信息
o := orm.NewOrm()
user := models.User{Name:userName.(string)}
o.Read(&user,"Name")
//获取地址数据
var addr models.Address
o.QueryTable("Address").RelatedSel("User").Filter("User__Id",user.Id).Filter("Is_default",true).One(&addr)
//向视图中传递数据
this.Data["addr"] = addr
this.Data["userName"] = username
this.Layout = "layout.html"
this.TplName = "user_center_Site.html"
4.3处理添加默认地址业务
4.3.1获取视图传过来的数据
根据显示的界面,我们能发现,添加地址传递过来了name,address,邮编,电话号码数据,我们第一步先获取这些数据,代码如下:
//获取传递的数据
name := this.GetString("receiverName")
address := this.GetString("address")
zipCode:=this.GetString("zipCode")
phoneNum:=this.GetString("phoneNum")
4.3.2数据校验
获取数据之后对数据进行判空操作(想具体点的话也可以对邮编和电话号码做正则匹配判断格式是否正确)
代码如下:
//数据校验
if name == ""||address==""||zipCode==""||phoneNum==""{
this.Data["errmsg"] = "添加地址数据不能为空"
this.TplName = "user_center_site.html"
return
}
4.3.3赋值操作
在插入数据库之前,我们要给操作的对象进行赋值。在我们浏览电商网站的时候,一般情况下,一个用户只允许一个默认地址,这里我们把业务设计为每次添加的地址都为默认地址,所以添加的时候需要把原来的默认地址改为非默认地址,代码如下:
//赋值操作
o := orm.NewOrm()
add := models.Address{}
//把原来的默认地址改为非默认地址
add.Is_default = true
err := o.Read(&add,"Is_default")
if err == nil{//如果查询到了is_default为true的数据说明有默认地址,把这条数据的默认地址更新为非默认地址,若果查不到默认地址,直接赋值
add.Is_default = false
o.Update(&add)
}
add.User = &user
add.Addr = address
add.Phone = phoneNum
add.Receiver = name
add.Zip_code = zipCode
add.Is_default = true
4.3.4插入数据库数据
赋值之后插入数据库,然后返回当前页面查看插入结果,代码如下:
_,err = o.Insert(&add)
if err != nil{
this.Data["errmsg"] = "插入地址信息错误"
this.TplName = "user_center_site.html"
return
}
this.Redirect("/goods/UserCenterSite",302)
4.3.5完整代码
//获取session数据
username := this.GetSession("userName")
//根据用户名获取用户信息
user := GetUser(username.(string))
//获取传递的数据
name := this.GetString("receiverName")
address := this.GetString("address")
zipCode:=this.GetString("zipCode")
phoneNum:=this.GetString("phoneNum")
//数据校验
if name == ""||address==""||zipCode==""||phoneNum==""{
this.Data["errmsg"] = "添加地址数据不能为空"
this.TplName = "user_center_site.html"
return
}
//插入数据库
o := orm.NewOrm()
add := models.Address{}
//把原来的默认地址改为非默认地址
add.Is_default = true
err := o.Read(&add,"Is_default")
if err == nil{
add.Is_default = false
o.Update(&add)
}
add.User = &user
add.Addr = address
add.Phone = phoneNum
add.Receiver = name
add.Zip_code = zipCode
add.Is_default = true
_,err = o.Insert(&add)
if err != nil{
this.Data["errmsg"] = "插入地址信息错误"
this.TplName = "user_center_site.html"
return
}
this.Redirect("/goods/UserCenterSite",302)
当前页面查看插入结果,代码如下:
_,err = o.Insert(&add)
if err != nil{
this.Data["errmsg"] = "插入地址信息错误"
this.TplName = "user_center_site.html"
return
}
this.Redirect("/goods/UserCenterSite",302)
4.3.5完整代码
//获取session数据
username := this.GetSession("userName")
//根据用户名获取用户信息
user := GetUser(username.(string))
//获取传递的数据
name := this.GetString("receiverName")
address := this.GetString("address")
zipCode:=this.GetString("zipCode")
phoneNum:=this.GetString("phoneNum")
//数据校验
if name == ""||address==""||zipCode==""||phoneNum==""{
this.Data["errmsg"] = "添加地址数据不能为空"
this.TplName = "user_center_site.html"
return
}
//插入数据库
o := orm.NewOrm()
add := models.Address{}
//把原来的默认地址改为非默认地址
add.Is_default = true
err := o.Read(&add,"Is_default")
if err == nil{
add.Is_default = false
o.Update(&add)
}
add.User = &user
add.Addr = address
add.Phone = phoneNum
add.Receiver = name
add.Zip_code = zipCode
add.Is_default = true
_,err = o.Insert(&add)
if err != nil{
this.Data["errmsg"] = "插入地址信息错误"
this.TplName = "user_center_site.html"
return
}
this.Redirect("/goods/UserCenterSite",302)