Django + React 電商專案練習 [???] - 後台實作 - 產品管理 CRUD - 上傳/更新產品圖片功能

Posted by Young on 2022-12-29
Estimated Reading Time 2 Minutes
Words 582 In Total

目標

解決原本圖片路徑只有純文字的情況:

before_image_upload.png

後端

views.py

  • 要得知是「哪一個產品」需要更新圖片,所以需傳入 product_idrequest.FILES.get('image') 取得上傳的圖片檔案
  • 先不用規範 permission_classes,這樣前端才不用在 config 額外取 token
1
2
3
4
5
6
7
8
@api_view(['POST'])
def uploadImage(request):
data = request.data
product_id = data['product_id']
product = Product.objects.get(id=product_id)
product.image = request.FILES.get('image')
product.save()
return Response('圖片上傳成功!')

urls.py

1
path('upload/', views.uploadProductImage,name="product_image_upload"),

前端

產品編輯前端頁面

  • 上傳 Handler 函式必須得是 async,因為要等待上傳完成後再執行下一步
  • <Form.File 相關寫法已在 react-bootstrap V5 版本以上被棄用,改用 <Form.Control type='file' />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ProductEditPage.js
const uploadImageHandler = async (e) => {
console.log(e.target.value);
};

return(
...
<Form.Group controlId='image' className='mb-3'>
<Form.Label>產品圖片</Form.Label>
<Form.Control required type='text' placeholder='請輸入產品圖片' value={image} onChange={(e) => setImage(e.target.value)}></Form.Control>
<Form.Control type='file' onChange={uploadImageHandler} />
</Form.Group>
{ImageUploading && <Loader />}
)

逐步慢慢測試,先查看上傳檔案後,主控台是否有印出檔案名稱

upload_test.png

確定有擷取到檔案後,用 e.target.files[0]; 取得檔案陣列中的第一個檔案,並宣告一個 FormData 物件,將檔案名稱、產品 ID 一併帶入 FormData 物件傳給後端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ProductEditPage.js
const uploadImageHandler = async (e) => {
const file = e.target.files[0];
const formData = new FormData();

formData.append("product_image", file); // product_image 後端 uploadProductImage view 接收的參數名稱
formData.append("product_id", productID);
try {
const { data } = await axios.post("/api/products/upload/", formData); // 呼叫後端 uploadProductImage view
setImage(data); // 後端的 return Response 值
setImageUploading(false); // 避免重複點擊
} catch (error) {
setImageUploading(false);
}
};
  • 使用 FormData 作為請求體時,Axios會自動檢測並設置適當的 Content-Type,不需要自己寫 config 設定,若後端有額外規定 permission_classes 就需要在config 設定 token
  • /api/products/upload/ 的路徑一定要跟後端 urls.py 設定的一模一樣,原本在 upload 這少加了 /,一直報 405 Error

完成後,應就能看到產品成功更換圖片,去專案的 static 資料夾下,也能看到上傳的新圖片檔

image_upload_done.png


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


留言版