如果直接阅读本文,您可能有些不知所云,这是因为我用很多篇幅讲了一个事情,如果想知道上下文,那么建议您从本专栏第22章看起:Python3开发–22–了解Django框架

一、购物车功能

购物车页面主要实现的功能是商品购买费用核算,该功能包括:加入商品到购物车、费用结算、删除购物车中的商品、支付(本功能涉及对接支付宝,我们不讲解)。

1、修改代码:shopper/views.py

from django.shortcuts import render, redirect
from commodity.models import *
from .models import *
from django.contrib.auth.decorators import login_required

# 设置用户的登录访问权限,如果未登录访问,则会跳转到指定的路由地址
@login_required(login_url='/shopper/login.html')
def shopcartView(request):
    # 设置共用模板base.html的模板变量
    title = '我的购物车'
    classContent = 'shopcarts'
    # 获取请求参数
    id = request.GET.get('id', '')
    quantity = request.GET.get('quantity', 1)
    userID = request.user.id
    # 存在请求参数id,则对模型CartInfos新增数据
    if id:
        CartInfos.objects.update_or_create(commodityInfos_id=id, user_id=userID, quantity=quantity)
        return redirect('shopper:shopcart')
    # 查询当前用户的购物车信息
    getUserId = CartInfos.objects.filter(user_id=userID)
    # 从当前用户的购物车信息获取商品id和购买属性
    commodityDcit = {x.commodityInfos_id: x.quantity for x in getUserId}
    # 从商品id获取商品详细信息
    commodityInfos = CommodityInfos.objects.filter(id__in=commodityDcit.keys())
    return render(request, 'shopcart.html', locals())

2、修改代码:templates/shopcart.html

<!-- 调用模板文件base.html并重写接口content -->
{% extends 'base.html' %}
{% load static %}
{% block content %}
    <div class="banner-bg w1200">
      <h3>夏季清仓</h3>
      <p>宝宝被子、宝宝衣服3折起</p>
    </div>
    <div class="cart w1200">
      <div class="cart-table-th">
        <div class="th th-chk">
          <div class="select-all">
            <div class="cart-checkbox">
              <input class="check-all check" id="allCheckked" type="checkbox" value="true">
            </div>
          <label>  全选</label>
          </div>
        </div>
        <div class="th th-item">
          <div class="th-inner">
            商品
          </div>
        </div>
        <div class="th th-price">
          <div class="th-inner">
            单价
          </div>
        </div>
        <div class="th th-amount">
          <div class="th-inner">
            数量
          </div>
        </div>
        <div class="th th-sum">
          <div class="th-inner">
            小计
          </div>
        </div>
        <div class="th th-op">
          <div class="th-inner">
            操作
          </div>
        </div>  
      </div>
      <div class="OrderList">
        <div class="order-content" id="list-cont">
        <!-- 遍历变量commodityInfos生成购物车的商品列表 -->
        {% for c in commodityInfos %}
          <ul class="item-content layui-clear">
            <li class="th th-chk">
              <div class="select-all">
                <div class="cart-checkbox">
                  <input class="CheckBoxShop check" id="" type="checkbox" num="all" name="select-all" value="true">
                </div>
              </div>
            </li>
            <li class="th th-item">
              <div class="item-cont">
                <a href="javascript:;"><img src="{{ c.img.url }}" alt=""></a>
                <div class="text">
                  <div class="title">{{ c.name }}</div>
                  <p><span>{{ c.sezes }}</span></p>
                </div>
              </div>
            </li>
            <li class="th th-price">
              <span class="th-su">{{ c.price }}</span>
            </li>
            <li class="th th-amount">
              <div class="box-btn layui-clear">
                <div class="less layui-btn">-</div>
                  {% for k, v in commodityDcit.items %}
                      {% if c.id == k %}
                        <input class="Quantity-input" value="{{ v }}" disabled="disabled">
                      {% endif %}
                  {% endfor %}
                <div class="add layui-btn">+</div>
              </div>
            </li>
            <li class="th th-sum">
              <span class="sum">0</span>
            </li>
            <li class="th th-op">
              <span class="dele-btn">删除</span>
              <p hidden="hidden">{{ c.id }}</p>
            </li>
          </ul>
          {% endfor %}

        </div>
      </div>

      <!-- 实现删除和结算按钮 -->
      <div class="FloatBarHolder layui-clear">
        <div class="th th-chk">
          <div class="select-all">
            <div class="cart-checkbox">
              <input class="check-all check" id="" name="select-all" type="checkbox"  value="true">
            </div>
            <label>  已选<span class="Selected-pieces">0</span>件</label>
          </div>
        </div>
        <div class="th batch-deletion">
          <span class="batch-dele-btn">删除全部</span>
          <p hidden="hidden" id="userId">{{ user.id }}</p>
        </div>
        <div class="th Settlement">
          <button class="layui-btn" id="settlement">结算</button>
        </div>
        <div class="th total">
          <p>应付:<span class="pieces-total">0</span></p>
        </div>
      </div>
    </div>
{% endblock content %}

<!-- 重写base.html的接口script,引入一些js脚本代码 -->
{% block script %}
  layui.config({
    base: '{% static 'js/' %}'
  }).use(['mm','jquery','element','car'],function(){
    var mm = layui.mm,$ = layui.$,element = layui.element,car = layui.car;
    car.init();

    $(function(){
    var counts = 0;
	$(".sum").each(function(i,e){
	  var quantity = $('.th-su')[i].innerHTML
      var price = $('.Quantity-input')[i].value
      e.innerHTML = (quantity * price).toFixed(2)
      counts = counts*1 + e.innerHTML*1
	});
    $(".pieces-total").text("¥" + counts.toFixed(2))
    });

    $("#settlement").on('click',function(){
        var total = $(".pieces-total").text()
        window.location = "{% url 'shopper:pays' %}?total=" + total
    })
});

{% endblock script %}

二、删除购物车的商品

1、修改代码:shopper/urls.py

from django.urls import path
from .views import *

urlpatterns = [
    # 第一个参数用于设置具体的路由地址
    # 第二个参数是指向index应用的views.py的某个视图函数
    # 第三个参数用于命名路由地址,是个可选参数
    path('.html', shopperView, name='shopper'),
    path('/login.html', loginView, name='login'),
    path('/logout.html', logoutView, name='logout'),
    path('/shopcart.html', shopcartView, name='shopcart'),
    # 删除路由
    path('/delete.html', deleteAPI, name='delete'),
]

2、修改代码:shopper/views.py

from django.http import JsonResponse
from .models import *

def deleteAPI(request):
    # 以字典格式表示,作为HTTP的相应内容
    result = {'state': 'success'}
    # 用于获取请求参数userId,如果不存在则设为空值
    userId = request.GET.get('userId', '')
    # 用于获取请求参数commodityId,如果不存在则设为空值
    commodityId = request.GET.get('commodityId', '')
    if userId:
        CartInfos.objects.filter(user_id=userId).delete()
    elif commodityId:
        CartInfos.objects.filter(commodityInfos_id=commodityId).delete()
    else:
        result = {'state': 'fail'}
    # 将变量result转换为json格式
    return JsonResponse(result)

三、总结

1、shopper/views.py修改过太多次了,我们来看看shopper/views.py现在长啥样了!

from django.http import JsonResponse
from django.shortcuts import render, redirect

from commodity.models import *
from .models import *
from django.core.paginator import Paginator
from django.core.paginator import EmptyPage
from django.core.paginator import PageNotAnInteger
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout, login, authenticate
from django.contrib.auth.models import User
from django.shortcuts import reverse
from .form import *

# def loginView(request):
#     # 定义变量,用于设置共用模板base.html的模板变量
#     title = '用户登录'
#     classContent = 'logins'
#
#     if request.method == 'POST':
#         # 获取请求参数username和password
#         username = request.POST.get('username', '')
#         password = request.POST.get('password', '')
#
#         # 查询username的数据是否存在内置模型User
#         if User.objects.filter(username=username):
#             # 验证账号密码与模型User的账号密码是否一致
#             user = authenticate(username=username, password=password)
#             # 如果通过验证,则使用内置函数login执行用户登录
#             # 登录成功后跳转到个人中心页面
#             if user:
#                 login(request, user)
#                 return redirect(reverse('shopper:shopper'))
#         # username的数据不存在内置模型User
#         else:
#             # 执行用户注册
#             state = '注册成功'
#             d = dict(username=username, password=password, is_staff=1, is_active=1)
#             user = User.objects.create_user(**d)
#             user.save()
#
#     return render(request, 'login.html', locals())

# def loginView(request):
#     title = '用户登录'
#     classContent = 'logins'
#     # 处理HTTP的POST请求
#     if request.method == 'POST':
#         infos = LoginForm(data=request.POST)
#         # 验证表单字段的数据是否正确
#         if infos.is_valid():
#             # 获取表单字段username和password的数据
#             data = infos.cleaned_data
#             username = data['username']
#             password = data['password']
#             # 查找模型User是否已有用户信息
#             if User.objects.filter(username=username):
#                 # 验证用户输入的账号密码是否正确
#                 user = authenticate(username=username, password=password)
#                 # 执行登录操作
#                 if user:
#                     login(request, user)
#                     return redirect(reverse('shopper:shopper'))
#             # 执行注册操作
#             else:
#                 state = '注册成功'
#                 d = dict(username=username, password=password, is_staff=1, is_active=1)
#                 user = User.objects.create_user(**d)
#                 user.save()
#         else:
#             # 获取错误信息,并以JSON格式输出
#             error_msg = infos.errors.as_json()
#             print(error_msg)
#     # 处理HTTP的GET请求
#     else:
#         infos = LoginForm()
#
#     return render(request, 'login.html', locals())

def loginView(request):
    title = '用户登录'
    classContent = 'logins'
    if request.method == 'POST':
        infos = LoginModelForm(data=request.POST)
        data = infos.data
        username = data['username']
        password = data['password']
        if User.objects.filter(username=username):
            user = authenticate(username=username, password=password)
            if user:
                login(request, user)
                return redirect(reverse('shopper:shopper'))
        else:
            state = '注册成功'
            d = dict(username=username, password=password, is_staff=1, is_active=1)
            user = User.objects.create_user(**d)
            user.save()
    else:
        infos = LoginModelForm()

    return render(request, 'login.html', locals())

# login_required设置用户登录访问权限,未登录情况下访问会自动跳转到指定路由地址
@login_required(login_url='/shopper/login.html')
def shopperView(request):
    # 变量title和classContent分别对应模板base.html中的模板变量title和classContent
    title = '个人中心'
    classContent = 'informations'
    fenye = request.GET.get('fenye', 1)
    # 处理已支付的订单
    shaixuan = request.GET.get('shaixuan', '')
    payTime = request.session.get('payTime', '')
    if shaixuan and payTime and shaixuan == payTime:
        payInfo = request.session.get('payInfo', '')
        OrderInfos.objects.create(**payInfo)
        del request.session['payTime']
        del request.session['payInfo']
    # 根据当前用户查询用户订单信息
    orderInfos = OrderInfos.objects.filter(user_id=request.user.id).order_by('-created')
    # 分页功能
    paginator = Paginator(orderInfos, 7)
    try:
        pages = paginator.page(fenye)
    except PageNotAnInteger:
        pages = paginator.page(1)
    except EmptyPage:
        pages = paginator.page(paginator.num_pages)
    return render(request, 'shopper.html', locals())

def logoutView(request):
    logout(request)
    return redirect(reverse('index:index'))

# 设置用户的登录访问权限,如果未登录访问,则会跳转到指定的路由地址
@login_required(login_url='/shopper/login.html')
def shopcartView(request):
    # 设置共用模板base.html的模板变量
    title = '我的购物车'
    classContent = 'shopcarts'
    # 获取请求参数
    id = request.GET.get('id', '')
    quantity = request.GET.get('quantity', 1)
    userID = request.user.id
    # 存在请求参数id,则对模型CartInfos新增数据
    if id:
        CartInfos.objects.update_or_create(commodityInfos_id=id, user_id=userID, quantity=quantity)
        return redirect('shopper:shopcart')
    # 查询当前用户的购物车信息
    getUserId = CartInfos.objects.filter(user_id=userID)
    # 从当前用户的购物车信息获取商品id和购买属性
    commodityDcit = {x.commodityInfos_id: x.quantity for x in getUserId}
    # 从商品id获取商品详细信息
    commodityInfos = CommodityInfos.objects.filter(id__in=commodityDcit.keys())
    return render(request, 'shopcart.html', locals())

def deleteAPI(request):
    # 以字典格式表示,作为HTTP的相应内容
    result = {'state': 'success'}
    # 用于获取请求参数userId,如果不存在则设为空值
    userId = request.GET.get('userId', '')
    # 用于获取请求参数commodityId,如果不存在则设为空值
    commodityId = request.GET.get('commodityId', '')
    if userId:
        CartInfos.objects.filter(user_id=userId).delete()
    elif commodityId:
        CartInfos.objects.filter(commodityInfos_id=commodityId).delete()
    else:
        result = {'state': 'fail'}
    # 将变量result转换为json格式
    return JsonResponse(result)

2、看看本节我们动过哪些代码文件:

python购物车结算金额 python购物车系统_后端