确认订单页面
当用户在购物车页面选中需要购买的商品或在商品的详情页面的时候点击直接购买的时候,会转到提交订单的页面。
购物车的页面
商品的详情页面:
通过上面用户的两种提交的请求,最终渲染出来的确认订单的页面如下:
要想渲染出来上面的页面,前端需要向后端传送的参数有:
1 如果用户在商品的详情页面点击直接购买需要向后端传送的参数包括: 商品的sku_id和商品的数量count
2 如果用户在购物车页面提交订单,那么需要向后端传送的数据只需要商品的sku_id就行。
后端的业务逻辑处理
1 用post请求接受前端传送的参数
2 用户必须是登陆的状态
3 参数的校验,如果商品sku_id为空,则直接返回到购物车页面
4 查询地址信息和商品信息 ,地址为空把值设为None,商品信息为空返回到购物车页面
5 业务逻辑处理
通过count是是否为None判断用户从商品的详情页面提交的数据还是从购物车页面提交过来的数据
1 如果count的值为空则用户是从购物车中提交过来的数据,每件商品的数量count可以通过遍历传送过来的商品的sku_ids从购物车中获取,把商品添加到购物车中
2 如果count的值不为空,数据就是从商品的详情页面提交而来,商品的数量就直接使用传送过来的count
6 通过遍历传送过来sku_id的列表把商品的数量,每个商品对应的总价,商品的总数量和包含运费的总金额当成商品对象的属性添加进去
7 把封装好数据返回给前端
后端的视图函数额代码如下:

配置请求的路径,在根路径urls中配置
import orders.urls
url(r'^orders/', include(orders.urls, namespace="orders")),
在订单的urls
from django.conf.urls import url
from . import views urlpatterns = [ url(r"^place$", views.PlaceOrderView.as_view(), name="place"), ]
当用户在购物车中提交:
生成的订单页面如下:
提交订单的页面 (生成订单信息表和订单商品表)
前端的页面如下所示
前端任务
根据后端的视图函数要生成的订单信息表和订单商品表,
前端需要向后端传送的数据: user 地址id、支付方式、商品id "1,2,3,4,5" 与 数量(从购物车中获取)
后端在生成两张表的时候,牵扯到如下的知识点:
1 事物
2 高并发
3 时间函数的使用
1 事务的使用:
数据库事务:http://python.usyiyi.cn/translate/django_182/topics/db/transactions.html
from django.db import transaction save_id = transaction.savepoint() # 创建保存点 transaction.savepoint_rollback(save_id) # 回退(回滚)到保存点 transaction.savepoint_commit(save_id) # 提交保存点
2 并发访问控制
当多个用户同时去抢同一个商品的时候,就有可能会出现库存不足,把一些错误的数据保存到数据库中
解决的方法: 采用悲观锁,采用乐观锁,采用队列,排队下单
悲观锁
SQL语句: select …where . for update
特点:在查询的时候立即上锁
乐观锁
查询时不锁数据,提交更改时进行判断
只有满足条件时才会修改数据,就是所有的信息都和最初自己查询的一致时,才会修改
update goods_sku set stock=new_stock, sales=new_sales where id=sku_id and stock=sku.stock
这里采用的是乐观锁
3 时间函数的使用
from django.utils import timezone order_id=timezone.now() # 获取当前的时间 order_id.strftime("%Y%m%d%H%M%S") # 把时间转换成字符串 strftime 将时间类型转换为字符串 strptime 将字符串转换为时间 python提供的时间模块 datetime time
这里用户必须是登陆的,如果未登录,返回json的数据用户未登陆,这里我自定义的装饰器,用来检验登录状态,如果用户未登录,返回json数据
在utils/views中,添加以下代码
from django.http import JsonResponse from functools import wraps # 自定义的装饰器,用来检验登录状态,如果用户未登录,返回json数据 def login_required_json(view_func): @wraps(view_func) def wrapper(request, *args, **kwargs): if not request.user.is_authenticated(): # 如果用户未登录, 返回json错误信息 return JsonResponse({"code": 1, "message": "用户未登录"}) else: # 如果用户已登录,则执行视图函数 return view_func(request, *args, **kwargs) return wrapper class LoginRequiredJsonMixin(object): """要求用户登录的功能补充逻辑, 使用自定义的login_required_json装饰器""" @classmethod def as_view(cls, **initkwargs): view = super(LoginRequiredJsonMixin, cls).as_view(**initkwargs) # 实际上就是调用的django提供的类视图基类的as_view return login_required_json(view)
自定义一个装饰器让视图函数支持事物的操作
在utils/views中,添加以下代码
from django.db import transaction class TransactionAtomicMixin(object): """支持事务的操作""" @classmethod def as_view(cls, **initkwargs): view = super(TransactionAtomicMixin, cls).as_view(**initkwargs) return transaction.atomic(view)
视图函数使用的时候通过导入继承上面的两个类就可以了
后端任务
根据前端传的参数生成订单信息表和商品的订单表
主要的业务逻辑的处理
1 接受前端传来的订单数据 ( user 地址(address_id)、支付方式(pay_method)、商品sku_ids----》 "1,2,3,4,5" 与 数量(从购物车中获取))
2 进行参数校验
1 判断地址是否存在,不存在返回 return JsonResponse({"code": 2, "message": "地址不存在"})
2 判断支付方式,如果不支持的支付,return JsonResponse({"code": 3, "message": "不支持的支付方式"})
3 把sku_ids的字符串(‘1,2,3,4,5’)转换成商品的ID列表[1,2,3,4,5]
4 获取购物车数据
5 自定义订单编号
6 创建事务用到的保存点·
7 生成订单信息表
8 遍历商品sku_ids,判断商品信息合理与否的同时保存到订单的商品表
9 采用乐观锁的方式,更新商品的库存,销量
10 在订单商品表中保存商品的信息
11 更新订单信息表数据,处理总金额总数量·
12 提交数据的事务操作
13 将处理后的购物车数据cart保存到redis中
14 返回给前端处理的结果, 返回json数据

在订单应用的urls中增加url的请求路径:
url(r"^commit$", views.CommitOrderView.as_view(), name="commit"),
当用户提交订单的信息成功后,在数据库中查看订单信息表
在数据库中查看订单商品表