Django + React 電商專案練習 [???] - 列出用戶的歷史訂單紀錄

Posted by Young on 2022-12-29
Estimated Reading Time 4 Minutes
Words 930 In Total

後端實作

在對應的 views 新增一個 API,取得此用戶的訂單紀錄。

1
2
3
4
5
6
7
8
9
# order_views.py
# 取得此用戶的訂單 進度-2024/12/12
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def getMyOrders(request):
user = request.user
orders = user.order_set.all()
serializer = OrderSerializer(orders, many=True)
return Response(serializer.data)

然後在 urls.py 新增一個路徑,對應到這個 API,記得要寫在 <str:pk>/ 之前,因為 django 匹配路徑時,是從上往下找,匹配完成其他路徑就不會再繼續匹配。

1
2
# 要寫在 <str:pk>/ 之前,django 匹配路徑時,是從上往下找,匹配完成其他路徑就不會再找
path('myorders/', views.getMyOrders, name='myorders'),

然後可以去 Postman 測試一下看後端是否建置成功,有的話應會出現此用戶的訂單列表回傳 JSON
user_order_list

前端實作

Constants 定義

先到 redux 裡面新增一個 orderConstants.js,定義取得此用戶的訂單紀錄的常數。

1
2
3
4
5
6
// orderConstants.js

export const ORDER_LIST_MY_REQUEST = "ORDER_LIST_MY_REQUEST";
export const ORDER_LIST_MY_SUCCESS = "ORDER_LIST_MY_SUCCESS";
export const ORDER_LIST_MY_FAIL = "ORDER_LIST_MY_FAIL";
export const ORDER_LIST_MY_RESET = "ORDER_LIST_MY_RESET";

Reducers 實作

然後將這些常數引入 orderReducers.js,並撰寫相關程式來處理這些常數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// orderReducers.js
import{
...
ORDER_LIST_MY_REQUEST,
ORDER_LIST_MY_SUCCESS,
ORDER_LIST_MY_FAIL,
ORDER_LIST_MY_RESET,
} from '../constants/orderConstants'

// 用戶歷史訂單
export const orderListMyReducer = (state = {orders:[]}, action) => {
switch (action.type) {
case ORDER_LIST_MY_REQUEST:
return {
loading: true,
};

case ORDER_LIST_MY_SUCCESS:
return {
loading: false,
// success:true
orders: action.payload,
};

case ORDER_LIST_MY_FAIL:
return {
loading: false,
error: action.payload,
};

case ORDER_LIST_MY_RESET:
return {
orders: [],
};
default:
return state;
}
};

然後在 store.js 引入這個 reducer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store.js
import { ...,orderListMyReducer } from "./reducers/orderReducers";
...
const store = configureStore({
reducer: {
// 儲存多個state的地方,到時會再各個component用useSelector指定要使用哪一個
...
// 訂單相關
...
orderListMy:orderListMyReducer,
},
preloadedState: initialState,
middleware: middleware,
});

Actions 實作

到 action 裡面新增一個 action 來取得此用戶的訂單紀錄,這個 action 就不需要 id,因為是取得此用戶的訂單紀錄,不像 payOrder 或 getOrderDetails 需要 id。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// orderActions.js
// 列出用戶的所有訂單
export const listMyOrders = () => async (dispatch, getState) => {
try {
dispatch({
type: ORDER_LIST_MY_REQUEST,
});

const {
userLogin: { userInfo },
} = getState();

const config = {
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${userInfo.token}`,
},
};

const { data } = await axios.get(`/api/orders/myorders/`, config);

dispatch({
type: ORDER_LIST_MY_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: ORDER_LIST_MY_FAIL,
payload: error.response && error.response.data.detail ? error.response.data.detail : error.message,
});
}
};

由於用戶登出後,要清空用戶的訂單紀錄,所以到 userActions.js 裡面新增一個 action 來清空用戶的訂單紀錄。

1
2
3
4
5
6
// userActions.js
export const logout = () => (dispatch) => {
localStorage.removeItem("userInfo");
...
dispatch({ type: ORDER_LIST_MY_RESET }) // 登出後清空訂單資料
};

訂單列表前端實作

接下來到 ProfilePage.js 來呼叫這個 action,並在 useEffect 裡面判斷是否有用戶登入,如果沒有登入就跳轉到登入頁面,如果有登入就取得此用戶的訂單紀錄。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ProfilePage.js
useEffect(() => {
if (!userInfo) {
// 如果沒有登入就跳轉到登入頁面
navigate("/login");
} else {
if (!user || !user.first_name || success) {
...
dispatch(listMyOrders());
} else {
...
}
}
}, [dispatch, navigate, userInfo, user, success]);

最後一步就是製作訂單列表的前端,這邊主要目的有:

  • 訂單列表在個人檔案的右側並佔據 5/6 的寬度,所以我們使用 Col=10 包住訂單區塊
  • 由於本身 Bootstrap 主題背景為白色,因此若要讓 Hover 效果明顯需要在 Table 加上 table-light 樣式,讓表格預設主題為淺白色
  • 判斷訂單是否已付款,如果已付款則顯示付款日期,如果未付款則顯示紅色的 X
  • 可以導向到訂單詳情頁面

table_code

由於 Table 標籤會導致此筆記頁面整個跑版,因此改用圖片代替


若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~


留言版