Django项目之Web端电商网站的实战开发(完结)

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

接着上一篇博客继续往下写 :Django项目之Web端电商网站的实战开发(五)_cdtaogang's blog-CSDN博客

非VIP用户请点击这里进行查阅

目录

一丶订单生成

二丶订单支付

三丶订单评论

四丶项目部署

五丶项目总结


一丶订单生成

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 +
  • 13
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cdtaogang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值