確認訂單頁面
當用戶在購物車頁面選中需要購買的商品或在商品的詳情頁面的時候點擊直接購買的時候,會轉到提交訂單的頁面。
購物車的頁面
商品的詳情頁面:
通過上面用戶的兩種提交的請求,最終渲染出來的確認訂單的頁面如下:
要想渲染出來上面的頁面,前端需要向后端傳送的參數有:
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"),
當用戶提交訂單的信息成功后,在數據庫中查看訂單信息表
在數據庫中查看訂單商品表