如果直接阅读本文,您可能有些不知所云,这是因为我用很多篇幅讲了一个事情,如果想知道上下文,那么建议您从本专栏第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、看看本节我们动过哪些代码文件: