18.1 订单结算

分析

  1. 本小节实现点击“去结算”按钮时,从redis中检索勾选的购物车数据,将其显示在结算页面,此环节并不生成订单记录。
  2. 只有登录用户才能结算,所以定义结算类视图OrderSettlementView时,需要继承LoginRequiredMixin类,让其验证登录状态。
  3. 订单相关数据有:收货地址、支付方式、商品名称、商品单位、商品价格、商品数量、金额小计、商品总数量、商品总金额、运费、实付款等,这些数据能前端转到视图类。
  4. 如果收货地址列表为空,点击“去结算”时,会跳转到收货地址页面;如果收货地址不为空,则跳转到订单提交页面;如果未设置收货地址,则不选中任何地址。
  5. 新增了订单视图类,需要在项目urls.py中新增对应的子路由。

实现

在orders应用的views中定义视图类OrderSettlementView,处理

import logging
from decimal import Decimal

from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from users.models import Address

logger = logging.getLogger('django')


# Create your views here.
class OrderSettlementView(LoginRequiredMixin, View):
    """订单视图类"""

    def get(self, request):
        # 获取当前登录用户对象
        user = request.user
        # 查询当前登录用户是否有收货地址
        try:
            addresses = Address.objects.filter(user=user, is_deleted=False)
            # 如果没有收货地址,那么就跳转到编辑收货地址页面
            if len(addresses) == 0:
                address_list = []
                context = {
                    'addresses': address_list
                }
                return render(request, 'user_center_site.html', context)
        except Exception as e:
            logger.error(e)
        # 从redis数据库中获取购物车数据  {b'1':b'1',b'2:b'2'}
        redis_conn = get_redis_connection('carts')
        redis_cart = redis_conn.hgetall('carts_%s' % user.id)
        # 从redis数据库中获取被勾选的商品sku_id  [b'1']
        redis_selected = redis_conn.smembers('selected_%s' % user.id)
        # 将被勾选的商品sku_id和数量组成一个新的数据
        new_cart_dict = {}
        for sku_id in redis_selected:
            new_cart_dict[int(sku_id)] = int(redis_cart[sku_id])
        # 通过sku模型类查询出在结算订单页面需要展示的商品sku
        sku_ids = new_cart_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids)

        total_count = 0
        total_amount = Decimal(0.00)
        for sku in skus:
            # 遍历skus为每个sku补充count(数量)和amount(小计)
            sku.count = new_cart_dict[sku.id]
            sku.amount = sku.price * sku.count
            # # 累加数量和金额
            total_count += sku.count
            total_amount += sku.amount
        # 定义运费10元
        freight = Decimal(10.00)
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight
        }
        return render(request, 'place_order.html', context=context)

在订单应用urls.py中定义子路由

from django.urls import path

from orders import views

app_name = 'orders'

urlpatterns = [
    # 订单
    path('orders/settlement/', views.OrderSettlementView.as_view(), name='settlement'),
]

在项目urls.py下增加根路由

path('', include('orders.urls'), name='orders'),

在模板templates根目录下增加place_order.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') }}">
    <script type="text/javascript" src="{{ static('js/vue-2.5.16.js') }}"></script>
    <script type="text/javascript" src="{{ static('js/axios-0.18.0.min.js') }}"></script>
</head>
<body>
<div id="app">
    <div class="header_con">
        <div class="header" v-cloak>
            <div class="welcome fl">欢迎来到小鱼商城!</div>
            <div class="fr">
                <div v-if="username" class="login_btn fl">
                    欢迎您:<em>[[ username ]]</em>
                    <span>|</span>
                    <a href="{{ url('users:logout') }}">退出</a>
                </div>
                <div v-else class="login_btn fl">
                    <a href="{{ url('users:login') }}">登录</a>
                    <span>|</span>
                    <a href="{{ url('users:register') }}">注册</a>
                </div>
                <div class="user_link fl">
                    <span>|</span>
                    <a href="{{ url('users:info') }}">用户中心</a>
                    <span>|</span>
                    <a href="{{ url('carts:info') }}">我的购物车</a>
                    <span>|</span>
{#                    <a href="{{ url('users:myorderinfo',args=(1,)) }}">我的订单</a>#}
                </div>
            </div>
        </div>
    </div>
    <div class="search_bar clearfix">
        <a href="{{ url('contents:index') }}" class="logo fl"><img src="{{ static('images/logo.png') }}"></a>
        <div class="search_wrap fl">
            <form method="get" action="/search/" class="search_con">
                <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
                <input type="submit" class="input_btn fr" name="" value="搜索">
            </form>
            <ul class="search_suggest fl">
                <li><a href="#">索尼微单</a></li>
                <li><a href="#">优惠15元</a></li>
                <li><a href="#">美妆个护</a></li>
                <li><a href="#">买2免1</a></li>
            </ul>
        </div>
    </div>
    <h3 class="common_title">确认收货地址</h3>
    <div class="common_list_con clearfix" id="get_site">
        <dl>
            {% if addresses %}
            <dt>寄送到:</dt>
            {% for address in addresses %}
            <dd @click="nowsite={{ address.id }}"><input type="radio" v-model="nowsite" value="{{ address.id }}">{{
                address.province }} {{ address.city }} {{ address.district }} ({{ address.title }}-{{ address.receiver }} 收) {{
                address.mobile }}
            </dd>
            {% endfor %}
            {% endif %}
        </dl>
        <a href="{{ url('users:address') }}" class="edit_site">编辑收货地址</a>
    </div>

    <h3 class="common_title">支付方式</h3>
    <div class="common_list_con clearfix">
        <div class="pay_style_con clearfix">
            <input type="radio" name="pay_method" value="1" v-model="pay_method">
            <label class="cash">货到付款</label>
            <input type="radio" name="pay_method" value="2" v-model="pay_method">
            <label class="zhifubao"></label>
        </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 sku in skus %}
        <ul class="goods_list_td clearfix">
            <li class="col01">{{loop.index}}</li>
            <li class="col02"><img src="/static/images/goods/{{ sku.default_image}}.jpg"></li>
            <li class="col03">{{ sku.name }}</li>
            <li class="col04"></li>
            <li class="col05">{{ sku.price }}元</li>
            <li class="col06">{{ sku.count }}</li>
            <li class="col07">{{ sku.amount }}元</li>
        </ul>
        {% endfor %}
    </div>

    <h3 class="common_title">总金额结算</h3>
    <div class="common_list_con clearfix">
        <div class="settle_con">
            <div class="total_goods_count"><em>{{ total_count }}</em>件商品,总金额<b>{{ total_amount }}元</b></div>
            <div class="transit">运费:<b>{{ freight }}元</b></div>
            <div class="total_pay">实付款:<b>{{ payment_amount }}元</b></div>
        </div>
    </div>

    <div class="order_submit clearfix">
        <a @click="on_order_submit" id="order_btn">提交订单</a>
    </div>

    <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 © 2024 北京小鱼商业股份有限公司 All Rights Reserved</p>
        <p>电话:010-****888 京ICP备*******8号</p>
    </div>
</div>
<script type="text/javascript">
    let default_address_id = "{{ user.default_address.id }}";
    let payment_amount = "{{ payment_amount }}";
</script>
<script type="text/javascript" src="{{ static('js/common.js') }}"></script>
<script type="text/javascript" src="{{ static('js/place_order.js') }}"></script>
</body>
</html>

解除cart.html中“去结算”按钮的注释。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值