在完成登录到用户提交订单,这一系列的类视图函数,会发现有大量的数据读写操作,像电商这类的项目,更多的是用户在浏览页面的次数比较多,所以在数据查询的场景中都会采用缓存,将用户第一次打开页面,到下一次重新浏览,这其间就可以提升用户打开页面的速度。
一、用户地址
用户地址的类视图,包括用户查询地址,也可以让用户创建新的收货地址。
在进入该视图之前,需要先验证用户是否登录,继承 LoginRequiredMinxin 类。
class LoginRequiredMixin(object):
"""验证用户的登录状态"""
@classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
class AddressView(LoginRequiredMixin, View):
"""用户地址"""
def get(self, request):
# 获取登录的用户
user = request.user
# 获取地址信息
#
# Address.objects.filter(user=user).order_by("create_time")[0]
#
# user.address_set.order_by("create_time")[0]
#
try:
address = user.address_set.latest("create_time")
except Address.DoesNotExist:
# 如果地址信息不存在
address = None
context = {
# "user": user, # django的模板中可以直接使用user模板变量
"address": address
}
return render(request, "user_center_site.html", context)
def post(self, request):
"""修改地址信息"""
user = request.user
recv_name = request.POST.get("recv_name")
addr = request.POST.get("addr")
zip_code = request.POST.get("zip_code")
recv_mobile = request.POST.get("recv_mobile")
if all([recv_name, addr, zip_code, recv_mobile]):
# address = Address(
# user=user,
# receiver_name=recv_name,
# detail_addr=addr,
# zip_code=zip_code,
# receiver_mobile=recv_mobile
# )
# address.save()
Address.objects.create(
user=user,
receiver_name=recv_name,
detail_addr=addr,
zip_code=zip_code,
receiver_mobile=recv_mobile
)
return redirect(reverse("users:address"))
二、订单确认
下单前需要得到用户购买的是哪件商品以及购买的数量;再计算出商品的价格和库存数量。
class PlaceOrderView(LoginRequiredMixin, View):
"""订单确认页面"""
def post(self, request):
# 获取参数
sku_ids = request.POST.getlist("sku_ids") # 要购买的商品id [1,2,3,4,5]
count = request.POST.get("count") # 商品的数量,从商品详情页面进入这个视图时需要传递,从购物车页面进入这个视图时不需要传递
# 商品详情页面的商品只有一个,所以数量也只有一个
# 校验参数
if not sku_ids:
# 跳转到购物车页面
return redirect(reverse("cart:info"))
redis_conn = get_redis_connection("default")
user_id = request.user.id
skus = []
total_count = 0
total_skus_amount = 0
trans_cost = 10 # 邮费,暂时写死
# 查询商品数据
if count is None:
# 如果是从购物车页面过来,商品的数量需要从redis中获取
cart = redis_conn.hgetall("cart_%s" % user_id)
total_amount = 0 # 包含了邮费和商品总金额的数值
# 遍历商品id,获取商品信息
for sku_id in sku_ids:
try:
sku = GoodsSKU.objects.get(id=sku_id)
except GoodsSKU.DoesNotExist:
# 跳转到购物车页面
return redirect(reverse("cart:info"))
# 读取商品的数量
sku_count = cart.get(sku_id.encode())
sku_count = int(sku_count)
# 计算商品的金额
amount = sku.price * sku_count
sku.amount = amount
sku.count = sku_count
skus.append(sku)
total_count += sku_count
total_skus_amount += amount
else:
# 如果是从商品详情页面过来,商品的数量直接就是count参数值
for sku_id in sku_ids:
try:
sku = GoodsSKU.objects.get(id=sku_id)
except GoodsSKU.DoesNotExist:
# 跳转到购物车页面
return redirect(reverse("cart:info"))
try:
sku_count = int(count)
except Exception:
# 跳回到商品的详情页面
return redirect(reverse("goods:detail", args=(sku_id,)))
# 判断库存
if sku_count > sku.stock:
# 跳回到商品的详情页面
return redirect(reverse("goods:detail", args=(sku_id,)))
# 计算商品的金额
amount = sku.price * sku_count
sku.amount = amount
sku.count = sku_count
skus.append(sku)
total_count += sku_count
total_skus_amount += amount
# 将商品存放到购物车中
redis_conn.hset("cart_%s" % user_id, sku_id, sku_count)
total_amount = total_skus_amount + trans_cost
# 地址信息
# address = Address.objects.filter(user_id=user_id)
try:
address = Address.objects.filter(user=request.user).latest("create_time")
except Address.DoesNotExist:
address = None
# 返回前端页面
context = {
"skus": skus,
"total_count": total_count,
"total_skus_amount": total_skus_amount,
"total_amount": total_amount,
"trans_cost": trans_cost,
"address": address,
"sku_ids": ",".join(sku_ids)
}
return render(request, "place_order.html", context)