说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
接着上一篇博客继续往下写 :Django项目之Web端电商网站的实战开发(五)_cdtaogang's blog-CSDN博客
目录
一丶订单生成
1.显示订单提交页面
- step1 在df_order/views中定义类视图post方法,显示订单提交页面
# /order/place
class OrderPlaceView(LoginRequiredMixin, View):
"""提交订单"""
def post(self, request):
"""显示提交订单页面"""
return render(request, 'place_order.html')
- step2 在df_order/urls中定义路由规则
url(r"^place$", OrderPlaceView.as_view(), name='place'), # 显示订单页
- step3 在place_order.html模板文件中,设置复选框checkbox的name为sku_ids以及value值为sku.id也就是商品id,因为当进行表单提交时,复选框的状态为未勾选状态时,则在headers from data表单数据中不会显示该商品的value值,即可以利用该点再后端获取提交订单页面中所有的数据
<form method="post" action="/order/place">
<li class="col01"><input type="checkbox" name="sku_ids" value="{
{ sku.id }}" checked></li>
<li class="col04"><input type="submit" value="去结算"></li>
</form>
- step4 在我的购物车页面点击去结算提交按钮,成功跳转到到提交订单页面
2.获取提交订单页面中的数据
- step1 判断用户是否登录状态,如果没有登录则跳转到登录页面
user = request.user
if not user.is_authenticated():
return redirect(reverse('user:login'))
- step2 获取表单中的sku_ids数据并进行校验
#1 获取表单中的sku_ids参数
sku_ids = request.POST.getlist("sku_ids") #[11,19,39,41]
#2 校验参数
if not sku_ids:
return redirect(reverse('cart:cart_show'))
- step3 获取redis连接对象,通过遍历sku_ids获取商品的信息,并获取数据库中商品的数量,计算出商品的小计,总计和总件数
conn = get_redis_connection("default")
cart_key = "cart_%d" % user.id
skus = []
total_price = 0 # 总金额
total_count = 0 # 总件数
# 遍历sku_ids获取每个商品的信息
for sku_id in sku_ids:
# 根据商品id获取商品的信息
sku = GoodsSKU.objects.get(id=sku_id)
# 根据商品id获取商品的数量
count = conn.hget(cart_key, sku_id)
# 计算商品的小计
amount = sku.price*int(count)
# 动态保存购买商品的数量和小计
sku.count = count
sku.amount = amount
# 商品信息对象保存到列表中
skus.append(sku)
# 累加金额与件数
total_count += int(count)
total_price += amount
- step4 设定运费金额,计算订单总金额组织模板上下文,返回给前端模板中
# 运费,一般在实际开发中需要单独创建一张表,当金额超过多少时免运费或者是多少钱,这里直接写死为10块
transit_price = 10
# 实际付款金额
total_pay = total_price + transit_price
# 获取收件人地址
addrs = Address.objects.filter(user=user)
# 组织模板上下文
context = {
'skus':skus,'total_count':total_count,
'total_price':total_price, 'transit_price':transit_price,
'total_pay':total_pay, 'addrs':addrs
}
return render(request, 'place_order.html', context)
- step5 在模板文件place_order.html中进行数据填坑
<div class="common_list_con clearfix">
<dl>
<dt>寄送到:</dt>
{% for addr in addrs %}
<dd><input type="radio" name="" checked="">{
{ addr.addr }} ({
{ addr.receiver }} 收) {
{ addr.phone }}</dd>
{% endfor %}
</dl>
<a href="{% url 'user:address' %}" class="edit_site">编辑收货地址</a>
</div>
{% for sku in skus %}
<ul class="goods_list_td clearfix">
<li class="col01">{
{ forloop.counter }}</li>
<li class="col02"><img src="{
{ sku.image.url }}"></li>
<li class="col03">{
{ sku.name }}</li>
<li class="col04">{
{ sku.unite }}</li>
<li class="col05">{
{ sku.price }}元</li>
<li class="col06">{
{ sku.count }}</li>
<li class="col07">{
{ sku.amount }}元</li>
</ul>
{% endfor %}
<div class="settle_con">
<div class="total_goods_count">共<em>{
{ total_count }}</em>件商品,总金额<b>{
{ total_price }}元</b></div>
<div class="transit">运费:<b>{
{ transit_price }}元</b></div>
<div class="total_pay">实付款:<b>{
{ total_pay }}元</b></div>
</div>
- step6 测试点击去结算按钮
- step7 在提交订单页面上的收货地址,应该将数据库中默认的收货地址is_default字段为1的复选框checkbox状态为checked,而不应该全部地址都是勾选状态,所以在place_order.html中进行如下判断显示
<dd><input type="radio" name="addr_id" value="{
{ addr.id }}" {% if addr.is_default %}checked{% endif %}>{
{ addr.addr }} ({
{ addr.receiver }} 收) {
{ addr.phone }}</dd>
- step8 刷新页面
3.创建订单
- step1 在提交订单页面,点击提交订单按钮,需要向后端传递提交订单页面中的收获地址和支付方式以及商品的id,即在place_order.html模板文件中需要手动去添加支付方式的value值对应后端订单模型类中的df_order_info表,收获地址前面已经进行设置了,所以不需要设置
<input type="radio" name="pay_style" value="1" checked>
<label class="cash">货到付款</label>
<input type="radio" name="pay_style" value="2">
<label class="weixin">微信支付</label>
<input type="radio" name="pay_style" value="3">
<label class="zhifubao"></label>
<input type="radio" name="pay_style" value="4">
<label class="bank">银行卡支付</label>
- step2 收货地址和支付方式已经在前端模板中设置好了,最后需要设置的就是商品的id,需要在后端中进行组织好传递到前端模板文件的数据格式,提交订单页面中的商品id已经保存到厚度那中skus列表中了,现在将该列表保存的商品id以逗号进行拼接,传递到前端模板中
sku_ids = ','.join(sku_ids) # 11,19,39,41
# 组织模板上下文
context = {
'skus':skus,'total_count':total_count,
'total_price':total_price, 'transit_price':transit_price,
'total_pay':total_pay, 'addrs':addrs,
'sku_ids':sku_ids
}
- step3 在前端模板中提交订单按钮中,定义标签属性sku_ids
<a href="javascript:;" sku_ids={
{ sku_ids }} id="order_btn">提交订单</a>
- step4 在place_order.html模板文件中进行提交订单js代码编写,获取用户选择的收货地址,支付方式以及购买的商品id,并通过ajax post方式向后端发送请求
$('#order_btn').click(function() {
// 获取用户选择的收货地址和支付方式以及商品id
addr_id = $('input[name="addr_id"]:checked').val();
pay_method = $('input[name="pay_style"]:checked').val();
sku_ids = $(this).attr('sku_ids');
csrf = $('input[name="csrfmiddlewaretoken"]').val();
params = {"addr_id":addr_id, "pay_method":pay_method, "sku_ids":sku_ids, "csrfmiddlewaretoken":csrf};
// 向后端/order/commit地址发送ajax post请求
$.post('/order/commit',params, function (data) {
});
- step5 紧接着在后端中定义类视图post方法,配置url路由
# /order/commit
class OrderCommitView(View):
"""创建订单"""
def post(self, request):
pass
url(r"^commit$", OrderCommitView.as_view(), name='commit'), # 创建订单
- step6 判断用户是否登录,获取参数以及校验参数完整性
user = request.user
if not user.is_authenticated():
return JsonResponse({"errno": 0, "error_msg": "请先登录"})
# 获取参数
addr_id = request.POST.get("addr_id")
pay_method = request.POST.get("pay_method")
sku_ids = request.POST.get("sku_ids")
# 校验参数
if not all([addr_id, pay_method, sku_ids]):
return JsonResponse({"errno": 1, "error_msg": "参数不完整"})
- step7 判断传递的支付方式以及收货地址是否合法
# 判断前端传递过来的支付方式是否存在
if pay_method not in OrderInfo.pay_method.key():
return JsonResponse({"errno": 2, "error_msg": "非法的支付方式"})
# 判断前端传递过来的收货地址是否存在
try:
addr = Address.objects.get(id=addr_id)
except Address.DoesNotExist:
return JsonResponse({"errno": 3, "error_msg": "非法的收货地址"})
- step8 向df_order_info表中插入记录,提交订单会在df_order_info以及df_order_goods这两张表中各产生一条记录,由于df_order_goods表外键为df_order_info表,所以需要先在df_order_info表中产生订单记录,在df_order_info表字段中,还需要去获取order_id,total_count,total_price,transit_price
#1 自定义order_id 20190408174330+用户id(作为唯一标识)
order_id = datetime.now().strftime("%Y%m%d%H%M%S") + str(user.id)
#2 总件数和总金额初始设置为0
total_count = 0
total_price = 0
#3 运费
transit_price = 10
# todo: 向df_order_info表中插入记录
order = OrderInfo.objects.create(
order_id=order_id, user=user,
addr=addr, pay_method=pay_method,
total_count=total_count, total_price=total_price,
transit_price=transit_price)
- step9 向df_order_goods表中插入记录,有多少种商品插入多少条记录
conn = get_redis_connection("default")
cart_key = "cart_%d" % user.id
sku_ids = sku_ids.split(',')
for sku_id in sku_ids:
# 获取商品信息
try:
sku = GoodsSKU.objects.get(id=sku_id)
except GoodsSKU.DoesNotExist:
return JsonResponse({"errno": 4, "error_msg": "商品不存在"})
# 从redis数据库中获取用户购买商品的数量
count = conn.hget(cart_key, sku_id)
# todo:向df_order_goods表中添加记录
OrderGoods.objects.create(
order=order,sku=sku,
count=count,price=sku.price)
# todo: 更新商品的库存和销量
sku.stock -= int(count)
sku.sales += int(count)
sku.save()
# todo: 累加计算订单商品的总数量和总价格
amount = sku.price * int(count)
total_count += int(count)
total_price +