GO语言开发天天生鲜项目第五天 购物车模块和订单模块
Posted 办公模板库 素材蛙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GO语言开发天天生鲜项目第五天 购物车模块和订单模块相关的知识,希望对你有一定的参考价值。
商品模块
商品详情页Js实现
在开始购物车模块之前,我们先把商品模块最后一个知识点实现。打开我们的商品详情页,这个页面的改变商品数量,获取总价的功能我们还没有实现。商品详情页的页面显示如下:
计算商品总价
思考什么时候计算商品总价?
当商品数量改变的时候需要重新计算商品总价。因为我们详情页这里可以添加商品数量,减少商品数量,修改商品数量以及刚加载页面的时候都需要计算商品总价,所以我们把计算商品总价这个业务封装成一个函数。
-
定义计算商品总价函数
function UpdateGoodsPrice()
-
获取商品数量和单价
由视图代码可以找到,商品单价标签是class=show_pirze的子标签,所以获取单价的代码为:
price = $('.show_pirze').children('em').text()
商品的数量标签是class=num_show的标签,则获取数量的代码为:
count = $('.num_show').val()
-
计算总价
在计算总价之前需要注意,我们这时候获取的price和count都是字符串类型,需要做类型转换之后才能做运算。代码如下:
//计算商品总价 price = parseFloat(price) count = parseInt(count) amount = price * count
-
设置总价
显示总价的标签为class=total的子标签,同时我们设置总价的时候,价格有两位小数点,设置总价代码如下:
$('.total').children('em').text(amount.toFixed(2)+'元')
全部函数代码如下:
//计算商品总价
function UpdateGoodsPrice()
//获取单价和数量
price = $('.show_pirze').children('em').text()
count = $('.num_show').val()
//计算商品总价
price = parseFloat(price)
count = parseInt(count)
amount = price * count
//设置总价
$('.total').children('em').text(amount.toFixed(2)+'元')
注意:当我们加载页面的时候就要计算总价,所以要在外面提前调用一下这个函数
添加商品数量
当点击+
超链接的时候显示栏的数量就添加1,这里我们通过js控制显示数量的增加
-
获取到按钮的点击事件
通过代码发现
+
这个超链接的class为add
,所以按钮的点击事件为:$('.add').click(function () )
-
获取原来显示框的数量
count = $('.num_show').val()
-
原来的数量加一
count = parseInt(count) + 1
直接获取的count类型为string类型,需要先转为Int类型,然后再进行加法运算
-
在显示框中显示
$('.num_show').val(count)
-
更新总价
//更新总价 UpdateGoodsPrice()
全部代码:
$('.add').click(function ()
//获取原来的数量,加一
count = $('.num_show').val()
count = parseInt(count) + 1
//重新设置数目
$('.num_show').val(count)
//更新总价
UpdateGoodsPrice()
)
减少商品数量
逻辑和增加商品数量一样,但是需要做一个简单的判断,代码如下:
$('.minus').click(function ()
//获取原来的数量,加一
count = $('.num_show').val()
count = parseInt(count) - 1
//对数据大小进行判断
if (count < 1)
count = 1
//重新设置数目
$('.num_show').val(count)
//更新总价
UpdateGoodsPrice()
)
手动设置商品数量
除了点击按钮外,我们还能够直接在input框中输入商品数量,然后获取总价。那我们什么时候获取这个手动的商品数量呢?一般是当这个input标签失去焦点的时候,我们开始获取手动设置的商品数量。
-
失去焦点的时候获取商品数量,相应函数如下:
$('.num_show').blur(function ()
-
获取输入的商品数量
count = $(this).val()
当响应函数内部获取某个标签的时候,如果这个标签和出发这个事件的标签一致,可以用this代替
-
对输入的数据进行校验
如果用户输入的数据是字母,一堆空格,或者小于1,这时候我们认为用户输入数据非法,需要手动设置一个正确的数值。代码如下:
if(isNaN(count) || count.trim().length == 0||parseInt(count)<1) count = 1
-
然后再次设置数量
$(this).val(count)
-
更新商品总价
UpdateGoodsPrice()
全部代码如下:
$('.num_show').blur(function ()
count = $(this).val()
if(isNaN(count) || count.trim().length == 0||parseInt(count)<1)
count = 1
$(this).val(count)
UpdateGoodsPrice()
)
购物车模块
1.添加购物车数据
我们这时候再回到商品详情页,这个页面有个添加购物车按钮。那我们就在这里实现这个功能。这时候需要思考一个问题,我们向数据库中添加购物车数据的时候,页面要全部刷新吗?
一般情况下,我们向数据库中添加购物车数据的时候,页面只是进行局部刷新。局部刷新我们一般用ajax来实现这个功能,那这里我们就用ajax发送请求。
请求
添加购物车,需要传递数据,我们一般是用post请求,函数名是$.post()
,有三个参数,第一个参数是请求路径,第二个参数是传递的数据(json格式的数据),第三个参数是成功后所执行的函数
所以在发送请求之前,我们需要先确定请求路径,添加购物车数据需要登陆的状态下才能进行,所以我们设置请求路径为/user/addCart。
接着我们要去构造传递的数据,添加购物车,需要把商品id
和对应的数量
传递给后台,这里我们设计数据格式为“skuid”:id,“count”:count。
最后是我们的函数。代码如下:
-
封装要传递的数据
我们要传递的数据为商品的id,所以我们需要获取这个id,但是这时候你发现,我们页面里面没有显示商品id的地方。那这里需要我们手动在页面里面添加这个内容,有两种解决方法:
第一种:隐藏域传值,这个方法我们前面用过,不做详细介绍。
第二种:给某一个标签添加一个自定义属性,获取这个属性的值,这里我们给
加入购物车
按钮添加一个商品ID属性,代码如下:获取自定义属性的值,使用attr()方法。具体代码如下:
skuid = $('#add_cart').attr("skuid")
获取商品数量,直接获取相应标签值即可,代码如下:
count = $('.num_show').val()
封装成一个json格式的数据包,代码如下:
params = 'skuid':skuid,'goodsCount':count
-
发送请求
$.post('/user/addCart',params,function (data) )
路由
ajax发送了请求之后,我们要在router.go中添加相对应的控制器和方法。
beego.Router("/user/addCart",&controllers.CartController,"post:HandleAddCart")
控制器
在路由指定了控制器和方法之后,我们就创建控制器并且实现HandleAddCart方法。
-
获取数据
skuid,err1 := this.GetInt("skuid") count,err2 := this.GetInt("goodsCount")
-
校验数据
校验数据传输是否正确
//返回数据 resp := make(map[string]interface) defer this.ServeJSON() //数据校验 if err1 != nil || err2 != nil resp["res"]=1 resp["errmsg"] = "获取数据信息错误" this.Data["json"] = resp return
注意,ajax传递过来的数据,我们回复的时候不再指定视图,而是回复给视图json格式的数据。那这里我们怎么给视图中传递json数据呢?
首先定义一个map[string]interface类型,用来存储返回的数据,然后指定传递的数据代码为:
this.Data["json"] = resp
接着调用传递数据函数:
this.ServeJSON()
不管能不能执行成功我们都要给ajax请求返回数据,所以这里我们可以直接defer调用函数的代码。
校验传过来的商品id是否有对应的商品数据
o := orm.NewOrm() var goods models.GoodsSKU goods.Id = skuid err := o.Read(&goods) if err != nil resp["res"]=2 resp["errmsg"] = "商品不存在"
校验添加商品的数量是否超出我们的库存
校验登陆状态
userName := this.GetSession("userName") if userName == nil resp["res"]=4 resp["errmsg"] = "用户未登录,请提前登录" this.Data["json"] = resp return
思考:我们这个请求都是在登陆状态下才能发的,那我这个校验还有意义没有?
-
处理数据
添加购物车数据其实就是向数据库中添加数据。那这时候我们思考以下几个问题:
第一:添加哪些数据?
第二:用哪种数据库?用哪种类型?
第一个问题的答案跟明确,我们要添加当前用户对应的商品,和商品数量。
根据第一个问题的答案我们分析出来,我们数据库中要存储用户信息,商品信息,商品数量,并且这三者还是一一对应的。那我们分析之后可以得出,用redis中的hash存储这个数据最合适。
那我们就给redis中设置一个hash值。
但是在添加这个记录之前,如果redis中该用户已经添加过该商品数据,那么我们做的就是累加操作。具体代码如下:
conn,_:=redis.Dial("tcp",":6379") preCount,_:=redis.Int(conn.Do("hget","cart_"+strconv.Itoa(user.Id),skuid)) conn.Do("hset","cart_"+strconv.Itoa(user.Id),skuid,count+preCount)
-
查询购物车中商品数量
//获取购物车商品个数 cartcount,_ :=redis.Int(conn.Do("hlen","cart_"+strconv.Itoa(user.Id)))
-
返回数据
resp["res"] = 5 resp["cartcount"]=cartcoun this.Data["json"] = resp
视图
这时候ajax能够拿到数据,我们就需要在回调函数里面做一个处理。具体处理如下(是一个执行动画操作,我们不需要详细了解,课堂上带你们看一下,知道即可):
$.post('goods/cartAdd',params,function (data)
if(data.res == 5)
//添加成功
$(".add_jump").css('left':$add_y+80,'top':$add_x+10,'display':'block')
$(".add_jump").stop().animate(
'left': $to_y+7,
'top': $to_x+7,
"fast", function()
$(".add_jump").fadeOut('fast',function()
$('#show_count').html(data.cartcount);
);
);
else
//添加失败
alert(data.errmsg)
)
到这里添加购物车内容基本实现,接着需要把项目中很多地方的添加购物车按钮都实现相应的超链接。
2.获取购物车条目数
添加完购物车内容,我们就需要去获取相关数据,我们发现在很多页面都需要展示购物车条目数,如图:
那么我们可以在后台封装一个获取购物车数据条目数的函数,加载各个页面的时候调用,代码如下:
func GetCartCount(this*beego.Controller)int
userName := this.GetSession("userName")
if userName == nil
return 0
o := orm.NewOrm()
var user models.User
user.Name = userName.(string)
o.Read(&user,"Name")
conn,_ := redis.Dial("tcp","192.168.110.81:6379")
rep,err :=conn.Do("hlen","cart_"+strconv.Itoa(user.Id))
cartCount ,_ :=redis.Int(rep,err)
return cartCount
3.购物车页面展示
请求
我们每个页面头部有一个导航栏,叫我的购物车,这个超链接就是发起购物车页面请求的。查看购物车数据需要在登陆的状态下才能够查看,所以这里我们设计访问购物车页面的请求为:/user/cart
路由
有了请求,需要到router.go中指定相应的控制器和方法。代码如下:
beego.Router("/user/cart",&controllers.CartController,"get:ShowCart")
控制器
接着我们在控制器中实现ShowCart函数。
-
从redis中获取数据
因为我们前面设计的redis中存储购物车数据的
key
值是cart_userId
,所以我们要先获取用户Id,代码如下:userName := this.GetSession("userName") o := orm.NewOrm() var user models.User user.Name = userName.(string) o.Read(&user,"Name")
有了key值,我们就可以获取相应数据。这里注意我们要获取购物车存储数据的类型为
hash
,获取所有数据的命令为hgetall
。这个命令返回的结果是一个map[string]int
切片。所以这里我们获取所有购物车数据的代码如下:conn,_:=redis.Dial("tcp","192.168.110.81:6379") defer conn.Close() //以map[string]int的形式获取购物车数据 reply,_:=redis.IntMap(conn.Do("hgetall","cart_"+strconv.Itoa(user.Id)))
-
获取相应的商品数据
这时候我们从redis数据库中获取到的是购物车中所有商品的ID和数量,视图中我们要获取的是确定的商品信息和数量 ,所以需要我们从数据库中获取到商品信息并和数量一起存储。这里要注意,我们这里又需要一个容器,存储商品信息和数量两个不同的类型,参考我们首页讲过的内容,这里我们还用
[]map[string]interface
,我们的切片的长度就是从redis数据库中获取了几条数据,获取所有商品的代码如下: -
计算总的价格和总数量
总价和总数量应该在循环获取商品的时候获取,这时候可以给总价个总数量做一个叠加。代码如下:
//循环遍历,获取购物车商品数据 totalCount := 0 totalPrice := 0 i := 0 for index,count := range reply temp := make(map[string]interface) var goods models.GoodsSKU id,_ := strconv.Atoi(index) goods.Id = id o.Read(&goods) temp["goods"] = goods temp["count"] = count cartGoods[i] = temp totalCount += count totalPrice += goods.Price * count i += 1
-
把获取到的总结,总数量,所有商品传递给视图
this.Data["totalCount"] = totalCount this.Data["totalPrice"] = totalPrice this.Data["goods"] = cartGoods
视图
视图中获取到数据之后,需要在视图中循环显示,代码如下:
range .goods
<ul class="cart_list_td clearfix">
<li class="col01"><input type="checkbox" name="skuids" value=".goods.Id" checked></li>
<li class="col02"><img src="http://192.168.110.81:8888/.goods.Image"></li>
<li class="col03">.goods.Name<br><em>.goods.Price元/.goods.Unite</em></li>
<li class="col04">.goods.Unite</li>
<li class="col05">.goods.Price元</li>
<li class="col06">
<div class="num_add">
<a href="javascript:;" class="add fl">+</a>
<input type="text" class="num_show fl" skuid = .goods.Id value=".count">
<a href="javascript:;" class="minus fl">-</a>
</div>
</li>
<li class="col07">.amount元</li>
<li class="col08"><a href="javascript:;" class="deleteCart">删除</a></li>
</u新星计划Django基于PythonWeb的Django框架设计实现天天生鲜系统-9购物车提交订单订单提交成功页面功能实现
购物车页面功能实现
购物车页面主要两个功能:
-
显示购物车商品详细数据.
-
增加商品删除功能.
我们在 cart 应用的 views.py 模块中增加 show_cart 视图函数, 来显示购物车商品数据, 代码如下:
def show_cart(request):
"""展示购物车商品"""
# 读取购物车商品列表
cart_goods_list = []
# 商品总数
cart_goods_count = 0
# 商品总价
cart_goods_money = 0
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
cart_goods = GoodsInfo.objects.get(id=goods_id)
cart_goods.goods_num = goods_num
cart_goods.total_money = int(goods_num) * cart_goods.goods_price
cart_goods_list.append(cart_goods)
# 累加购物车商品总数
cart_goods_count = cart_goods_count + int(goods_num)
# 累计商品总价
cart_goods_money += int(goods_num) * cart_goods.goods_price
return render(request, 'cart.html', {'cart_goods_list': cart_goods_list,
'cart_goods_count': cart_goods_count,
'cart_goods_money': cart_goods_money})
cart.html 模板代码数据如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>天天生鲜-购物车</title>
<link rel="stylesheet" type="text/css" href="/static/css/reset.css">
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
</head>
<body>
<div class="header_con">
<div class="header">
<div class="welcome fl">欢迎来到天天生鲜!</div>
</div>
</div>
<div class="search_bar clearfix">
<a href="index.html" class="logo fl"><img src="/static/images/logo.png"></a>
<div class="sub_page_name fl">| 购物车</div>
</div>
<div class="total_count">全部商品<em>{{ cart_goods_count }}</em>件</div>
<ul class="cart_list_th clearfix">
<li class="col01">商品名称</li>
<li class="col02">商品单位</li>
<li class="col03">商品价格</li>
<li class="col04">数量</li>
<li class="col05">小计</li>
<li class="col06">操作</li>
</ul>
{% for cart_goods in cart_goods_list %}
<ul class="cart_list_td clearfix">
<li class="col01"></li>
<li class="col02"><img src="/static/{{ cart_goods.goods_img }}"></li>
<li class="col03">奇异果<br><em>{{ cart_goods.goods_price }}元/{{ cart_goods.goods_unit }}</em></li>
<li class="col04">{{ cart_goods.goods_unit }}</li>
<li class="col05">{{ cart_goods.goods_price }}元</li>
<li class="col06">{{ cart_goods.goods_num }}</li>
<li class="col07">{{ cart_goods.goods_price }}元</li>
<li class="col08"><a href="/cart/remove_cart/?id={{ cart_goods.id }}">删除</a></li>
</ul>
{% endfor %}
<ul class="settlements">
<li class="col01">.</li>
<li class="col02">.</li>
<li class="col03">合计(不含运费):<span>¥</span><em>{{ cart_goods_money }}</em><br>共计<b>{{ cart_goods_count }}</b>件商品</li>
<li class="col04"><a href="/cart/place_order/">去结算</a></li>
</ul>
<div class="footer">
<div class="foot_link">
<a href="#">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2016 北京天天生鲜信息技术有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div>
</body>
</html>
如下模板代码用于显示购物车商品数据:
{% for cart_goods in cart_goods_list %}
<ul class="cart_list_td clearfix">
<li class="col01"></li>
<li class="col02"><img src="/static/{{ cart_goods.goods_img }}"></li>
<li class="col03">奇异果<br><em>{{ cart_goods.goods_price }}元/{{ cart_goods.goods_unit }}</em></li>
<li class="col04">{{ cart_goods.goods_unit }}</li>
<li class="col05">{{ cart_goods.goods_price }}元</li>
<li class="col06">{{ cart_goods.goods_num }}</li>
<li class="col07">{{ cart_goods.goods_price }}元</li>
<li class="col08"><a href="/cart/remove_cart/?id={{ cart_goods.id }}">删除</a></li>
</ul>
{% endfor %}
如下代码显示购物车的总商品数量、商品总价:
<li class="col03">合计(不含运费):<span>¥</span><em>{{ cart_goods_money }}</em><br>共计<b>{{ cart_goods_count }}</b>件商品</li>
我们的购物车页面提供了删除购物车商品的功能, 该功能的链接代码如下:
<li class="col08"><a href="/cart/remove_cart/?id={{ cart_goods.id }}">删除</a></li>
当用户要删除某个购物车商品时, 该请求由 cart 应用下的 remove_cart 视图来处理, 该视图函数实现如下:
def remove_cart(request):
"""删除购物车商品"""
# 获得要删除的商品ID
goods_id = request.GET.get('id', '')
if goods_id:
# 获得上一页面地址
prev_url = request.META['HTTP_REFERER']
# 写入到 cookie 中
response = redirect(prev_url)
# 判断商品是否存在
goods_count = request.COOKIES.get(goods_id, '')
if goods_count:
response.delete_cookie(goods_id)
return response
首先要获得删除商品的 ID, 代码如下:
goods_id = request.GET.get('id', '')
如果该商品在购物车中存在, 则删除它. 删除完成之后跳转到上一页面, 也就是购物车页面, 代码如下:
if goods_id:
# 获得上一页面地址
prev_url = request.META['HTTP_REFERER']
# 写入到 cookie 中
response = redirect(prev_url)
# 判断商品是否存在
goods_count = request.COOKIES.get(goods_id, '')
if goods_count:
response.delete_cookie(goods_id)
提交订单页面功能实现
当购物车商品数据确认无误之后, 点击结算按钮跳转到订单提交页面, 在该页面用户就需要填写收货地址、联系电话、联系人等信息.
我们在 cart 应用下的 views.py 模块中新增如下视图函数:
def place_order(request):
"""提交订单页面"""
# 读取购物车商品列表
cart_goods_list = []
# 商品总数
cart_goods_count = 0
# 商品总价
cart_goods_money = 0
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
cart_goods = GoodsInfo.objects.get(id=goods_id)
cart_goods.goods_num = goods_num
cart_goods.total_money = int(goods_num) * cart_goods.goods_price
cart_goods_list.append(cart_goods)
# 累加购物车商品总数
cart_goods_count = cart_goods_count + int(goods_num)
# 累计商品总价
cart_goods_money += int(goods_num) * cart_goods.goods_price
return render(request, 'place_order.html', {'cart_goods_list': cart_goods_list,
'cart_goods_count': cart_goods_count,
'cart_goods_money': cart_goods_money})
并在 ttsx/urls.py 模块中配置该视图对应的请求网址, 新增配置如下:
from django.conf.urls import include, url
from django.contrib import admin
from goods.views import index # 导入视图函数
from goods.views import detail
from goods.views import goods
from cart.views import add_cart
from cart.views import show_cart
from cart.views import place_order
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^index/$', index),
url(r'^detail/$', detail),
url(r'^cart/add_cart/$', add_cart),
url(r'^goods/$', goods),
url(r'^cart/show_cart/$', show_cart),
url(r'^cart/place_order/$', place_order),
]
cart.html 模板代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>天天生鲜-提交订单</title>
<link rel="stylesheet" type="text/css" href="/static/css/reset.css">
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
</head>
<body>
<div class="header_con">
<div class="header">
<div class="welcome fl">欢迎来到天天生鲜!</div>
</div>
</div>
<div class="search_bar clearfix">
<a href="/" class="logo fl"><img src="/static/images/logo.png"></a>
<div class="sub_page_name fl">| 提交订单</div>
</div>
<h3 class="common_title">商品列表</h3>
<div class="common_list_con clearfix">
<ul class="goods_list_th clearfix">
<li class="col01">商品名称</li>
<li class="col02">商品单位</li>
<li class="col03">商品价格</li>
<li class="col04">数量</li>
<li class="col05">小计</li>
</ul>
{% for cart_goods in cart_goods_list %}
<ul class="goods_list_td clearfix">
<li class="col01">1</li>
<li class="col02"><img src="/static/{{ cart_goods.goods_img }}"></li>
<li class="col03">{{ cart_goods.goods_name }}</li>
<li class="col04">{{ cart_goods.goods_unit }}</li>
<li class="col05">{{ cart_goods.goods_price }}元</li>
<li class="col06">{{ cart_goods.goods_num }}</li>
<li class="col07">{{ cart_goods.total_money }}元</li>
</ul>
{% endfor %}
</div>
<h3 class="common_title">收货地址</h3>
<form action="/cart/submit_order/" method="post">
{% csrf_token %}
<div class="common_list_con clearfix">
<dl>
<dd>
<table>
<tr>
<td>收货地址:</td><td><input style="width: 350px; height: 23px;" type="text" name="addr"></td>
</tr>
<tr>
<td>收货人:</td><td><input style="width: 350px; height: 23px;" type="text" name="recv"></td>
</tr>
<tr>
<td>联系电话:</td><td><input style="width: 350px; height: 23px;" type="text" name="tele"></td>
</tr>
<tr>
<td>备注:</td><td><textarea style="width: 350px; height: 100px; font-size: 12px;" name="extra"></textarea></td>
</tr>
</table>
</dd>
</dl>
</div>
<h3 class="common_title">支付方式</h3>
<div class="common_list_con clearfix">
<div class="pay_style_con clearfix">
<input type="radio" name="pay_style" checked>
<label class="cash">货到付款</label>
</div>
</div>
<h3 class="common_title">总金额结算</h3>
<div class="common_list_con clearfix">
<div class="settle_con">
<div class="total_goods_count">共<em>{{ cart_goods_count }}</em>件商品,总金额<b>{{ cart_goods_money }}元</b></div>
<div class="transit">运费:<b>10元</b></div>
<div class="total_pay">实付款:<b>{{ cart_goods_money|add:10 }}元</b></div>
</div>
</div>
<div class="order_submit clearfix">
<input type="submit" value="提交订单"/>
</div>
</form>
<div class="footer">
<div class="foot_link">
<a href="#">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2016 北京天天生鲜信息技术有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div>
<div class="popup_con">
<div class="popup">
<p>订单提交成功!</p>
</div>
<div class="mask"></div>
</div>
</body>
</html>
我们在模板中新增了一个 form 表单用于提交订单数据, 代码如下:
<form action="/cart/submit_order/" method="post">
{% csrf_token %}
<div class="common_list_con clearfix">
<dl>
<dd>
<table>
<tr>
<td>收货地址:</td><td><input style="width: 350px; height: 23px;" type="text" name="addr"></td>
</tr>
<tr>
<td>收货人:</td><td><input style="width: 350px; height: 23px;" type="text" name="recv"></td>
</tr>
<tr>
<td>联系电话:</td><td><input style="width: 350px; height: 23px;" type="text" name="tele"></td>
</tr>
<tr>
<td>备注:</td><td><textarea style="width: 350px; height: 100px; font-size: 12px;" name="extra"></textarea></td>
</tr>
</table>
</dd>
</dl>
</div>
<h3 class="common_title">支付方式</h3>
<div class="common_list_con clearfix">
<div class="pay_style_con clearfix">
<input type="radio" name="pay_style" checked>
<label class="cash">货到付款</label>
</div>
</div>
<h3 class="common_title">总金额结算</h3>
<div class="common_list_con clearfix">
<div class="settle_con">
<div class="total_goods_count">共<em>{{ cart_goods_count }}</em>件商品,总金额<b>{{ cart_goods_money }}元</b></div>
<div class="transit">运费:<b>10元</b></div>
<div class="total_pay">实付款:<b>{{ cart_goods_money|add:10 }}元</b></div>
</div>
</div>
<div class="order_submit clearfix">
<input type="submit" value="提交订单"/>
</div>
</form>
该 form 表单将订单数据提交到 /cart/submit_order/ 页面进行处理, 代码如下:
<form action="/cart/submit_order/" method="post">
{% csrf_token %}
其中 {% csrf_token %} 主要用于安全设置, 这是django提供的防护错误, 用于防护跨站请求伪造. 在如果提交的表单是以 post 方式提交的话, 那么需要我们在 form 表单内部加上该代码.
代码 {{ cart_goods_money|add:10 }} 的含义为 cart_goods_money 的值 加上10. add 是django模板语法中提供的过滤器函数, 使用语法就是:
{{ 变量|过滤器函数:参数 }}
用户填写完收货信息之后, 点击提交订单按钮, 将表单提交到了 /cart/submit_order/ 页面, 我们在 cart 应用下的 views.py 模块中新增 submit_order 视图函数用于处理订单提交. 该视图函数实现如下:
def submit_order(request):
"""保存订单"""
# 获得订单信息
addr = request.POST.get('addr', '')
recv = request.POST.get('recv', '')
tele = request.POST.get('tele', '')
extra = request.POST.get('extra', '')
# 保存订单信息
order_info = OrderInfo()
order_info.order_addr = addr
order_info.order_tele = tele
order_info.order_recv = recv
order_info.order_extra = extra
# 生成订单编号
order_info.order_id = str(int(time.time() * 1000)) + str(int(time.clock() * 1000000))
order_info.save()
# 跳转页面
response = redirect('/cart/submit_success/?id=%s' % order_info.order_id)
# 保存订单商品信息
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
# 查询商品信息
cart_goods = GoodsInfo.objects.get(id=goods_id)
# 创建订单商品信息
order_goods = OrderGoods()
order_goods.goods_info = cart_goods
order_goods.goods_order = order_info
order_goods.goods_num = goods_num
order_goods.save()
# 删除购物车信息
response.delete_cookie(goods_id)
return response
配置该视图与网址的对应关系, 编辑 ttsx/urls.py 模块如下:
from django.conf.urls import include, url
from django.contrib import admin
from goods.views import index # 导入视图函数
from goods.views import detail
from goods.views import goods
from cart.views import add_cart
from cart.views import show_cart
from cart.views import place_order
from cart.views import submit_order
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^index/$', index),
url(r'^detail/$', detail),
url(r'^cart/add_cart/$', add_cart),
url(r'^goods/$', goods),
url(r'^cart/show_cart/$', show_cart),
url(r'^cart/place_order/$', place_order),
url(r'^cart/submit_order/$', submit_order),
]
首先我们获得表单提交的数据, 这里需要大家注意, 如果表单以 post 方提交的话, 那么表单中提交的数据会被存储在 request 对象的 POST 字典中.
# 获得订单信息
addr = request.POST.get('addr', '')
recv = request.POST.get('recv', '')
tele = request.POST.get('tele', '')
extra = request.POST.get('extra', '')
我们的订单信息保存分为两部分, 第一部分是订单基本信息, 存储在 OrderInfo 模型所对应的数据库表中, 代码如下:
# 保存订单信息
order_info = OrderInfo()
order_info.order_addr = addr
order_info.order_tele = tele
order_info.order_recv = recv
order_info.order_extra = extra
# 生成订单编号
order_info.order_id = str(int(time.time() * 1000)) + str(int(time.clock() * 1000000))
order_info.save()
然后将订单中的商品信息存储在 OrderGoods 模型所对应的表中. 首先我们创建了一个重定向响应对象, 指定订单提交成功之后要跳转的页面:
# 跳转页面
response = redirect('/cart/submit_success/?id=%s' % order_info.order_id)
然后保存订单商品信息到数据库中, 并删除购物车中商品数据, 代码如下:
# 保存订单商品信息
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
# 查询商品信息
cart_goods = GoodsInfo.objects.get(id=goods_id)
# 创建订单商品信息
order_goods = OrderGoods()
order_goods.goods_info = cart_goods
order_goods.goods_order = order_info
order_goods.goods_num = goods_num
order_goods.save()
# 删除购物车信息
response.delete_cookie(goods_id)
当订单提交成功之后, 删除购物车中的商品信息, 跳转到 submit_success 页面, 并传递过去订单编号.
以上是关于GO语言开发天天生鲜项目第五天 购物车模块和订单模块的主要内容,如果未能解决你的问题,请参考以下文章
新星计划Django基于PythonWeb的Django框架设计实现天天生鲜系统-10订单提交成功页面功能实现
Django基于PythonWeb的Django框架设计实现天天生鲜系统-1
天天生鲜(Python)Django项目学习资料(视频源码)