# 後端實作
在對應的 views 新增一個 API,取得此用戶的訂單紀錄。
# 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 匹配路徑時,是從上往下找,匹配完成其他路徑就不會再繼續匹配。
# 要寫在 <str:pk>/ 之前,django 匹配路徑時,是從上往下找,匹配完成其他路徑就不會再找
path('myorders/', views.getMyOrders, name='myorders'),
然後去 Postman 測試一下看後端是否建置成功,有的話應會出現此用戶的訂單列表回傳 JSON 資料。
# 前端實作
# Constants 定義
先到 redux 裡面新增一個 orderConstants.js,定義取得此用戶的訂單紀錄的常數。
// 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,並撰寫相關程式來處理這些常數。
// 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
// 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。
// 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 來清空用戶的訂單紀錄。
// userActions.js
export const logout = () => (dispatch) => {
localStorage.removeItem("userInfo");
...
dispatch({ type: ORDER_LIST_MY_RESET }) // 登出後清空訂單資料
};
# 訂單列表前端實作
接下來到 ProfilePage.js 來呼叫這個 action,並在 useEffect 裡面判斷是否有用戶登入,如果沒有登入就跳轉到登入頁面,如果有登入就取得此用戶的訂單紀錄。
// 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 標籤會導致此筆記頁面整個跑版,因此改用圖片代替,成品如下:

