將 CSV 檔案上傳到 Django REST(尤其是在原子設定中)是一項簡單的任務,但讓我感到困惑,直到我發現了一些我將與您分享的技巧。
在本文中,我將使用郵遞員(代替前端),並將分享您需要在郵遞員上設定什麼才能透過圖片發送請求。
我們想要的
方法
pip 安裝 pandas
對於值單元格,按一下「選擇檔案」按鈕並上傳 CSV。請看下面的截圖
在 headers 下,設定 Content-Disposition 並將值設為 form-data;名稱=「檔案」;檔案名稱=「你的檔案名稱.csv」。將 your_file_name.csv 替換為您的實際檔案名稱。檢查下面的螢幕截圖。
from rest_framework import status from rest_framework.views import APIView from rest_framework.parsers import FileUploadParser from rest_framework.response import Response from .models import BiodataModel from django.db import transaction import pandas as pd class UploadCSVFile(APIView): parser_classes = [FileUploadParser] def post(self,request): csv_file = request.FILES.get('file') if not csv_file: return Response({"error": "No file provided"}, status=status.HTTP_400_BAD_REQUEST) # Validate file type if not csv_file.name.endswith('.csv'): return Response({"error": "File is not CSV type"}, status=status.HTTP_400_BAD_REQUEST) df = pd.read_csv(csv_file, delimiter=',',skiprows=3,dtype=str).iloc[:-1] df = df.where(pd.notnull(df), None) bulk_data=[] for index, row in df.iterrows(): try: row_instance= BiodataModel( name=row.get('name'), age=row.get('age'), address =row.get('address')) row_instance.full_clean() bulk_data.append(row_instance) except Exception as e: return Response({"error": f'Error at row {index + 2} -> {e}'}, status=status.HTTP_400_BAD_REQUEST) try: with transaction.atomic(): BiodataModel.objects.bulk_create(bulk_data) except Exception as e: return Response({"error": f'Bulk create error--{e}'}, status=status.HTTP_400_BAD_REQUEST) return Response({"msg":"CSV file processed successfully"}, status=status.HTTP_201_CREATED)
解釋上面的程式碼:
程式碼首先匯入必要的套件,定義基於類別的視圖並設定解析器類別(FileUploadParser)。類別中 post 方法的第一部分嘗試從 request.FILES 取得檔案並檢查其可用性。
然後進行次要驗證,透過檢查擴展名來檢查它是否是 CSV。
下一部分將其載入到 pandas 資料框中(非常像電子表格):
df = pd.read_csv(csv_file, delimiter=',',skiprows=3,dtype=str).iloc[:-1]
我將解釋一些傳遞給載入函數的參數:
跳船
在讀取載入的 csv 檔案時,應該注意的是,本例中的 csv 是透過網路傳遞的,因此一些元資料(例如內容)會加入到檔案的開頭和結尾。這些東西可能很煩人,而且不是逗號分隔值 (csv) 形式,因此實際上可能會引發解析錯誤。這解釋了為什麼我使用skiprows=3來跳過包含元資料和標題的前3行並直接落在csv的正文上。如果刪除跳過行或使用較少的數字,也許您可能會收到以下錯誤:錯誤標記資料。 C 錯誤,或者您可能會注意到從標頭開始的資料。
dtype=str
Pandas 喜歡嘗試猜測某些列的資料類型來證明自己很聰明。我希望所有值都是字串,所以我使用 dtype=str
分隔符號
指定單元格的分離方式。預設值通常是逗號。
iloc[:-1]
我必須使用 iloc 對資料幀進行切片,刪除 df 末尾的元資料。
然後,下一行 df = df.where(pd.notnull(df), None) 將所有 NaNvalues 轉換為 None。 NaNi 是 pandas 用來表示 None 的替代值。
下一個區塊有點棘手。我們循環資料幀中的每一行,使用BiodataModel 實例化行數據,使用full_clean() 方法執行模型級驗證(不是序列化器級),因為批量創建會繞過Django 驗證,然後將我們的創建操作添加到名為的列表中批量資料。是啊,添加還沒運行!請記住,我們正在嘗試執行原子操作(在批次層級),因此我們想要全部或無。單獨保存行不會為我們帶來全部或沒有行為。
然後是最後一個重要部分。在 transaction.atomic() 區塊(提供所有或不提供行為)中,我們執行 BiodataModel.objects.bulk_create(bulk_data) 來一次儲存所有行。
還有一件事。注意 for 迴圈中的索引變數和 except 區塊。在 except 區塊錯誤訊息中,我將 2 加到從 df.iterrows() 派生的索引變數中,因為在 Excel 檔案中查看時,該值與它所在的行不完全相符。 except 區塊會捕獲任何錯誤,並在 Excel 中開啟時建構一條具有確切行號的錯誤訊息,以便上傳者可以輕鬆找到 Excel 檔案中的行!
感謝您的閱讀! ! !
使用的工具版本
from rest_framework import status from rest_framework.views import APIView from rest_framework.parsers import FileUploadParser from rest_framework.response import Response from .models import BiodataModel from django.db import transaction import pandas as pd class UploadCSVFile(APIView): parser_classes = [FileUploadParser] def post(self,request): csv_file = request.FILES.get('file') if not csv_file: return Response({"error": "No file provided"}, status=status.HTTP_400_BAD_REQUEST) # Validate file type if not csv_file.name.endswith('.csv'): return Response({"error": "File is not CSV type"}, status=status.HTTP_400_BAD_REQUEST) df = pd.read_csv(csv_file, delimiter=',',skiprows=3,dtype=str).iloc[:-1] df = df.where(pd.notnull(df), None) bulk_data=[] for index, row in df.iterrows(): try: row_instance= BiodataModel( name=row.get('name'), age=row.get('age'), address =row.get('address')) row_instance.full_clean() bulk_data.append(row_instance) except Exception as e: return Response({"error": f'Error at row {index + 2} -> {e}'}, status=status.HTTP_400_BAD_REQUEST) try: with transaction.atomic(): BiodataModel.objects.bulk_create(bulk_data) except Exception as e: return Response({"error": f'Bulk create error--{e}'}, status=status.HTTP_400_BAD_REQUEST) return Response({"msg":"CSV file processed successfully"}, status=status.HTTP_201_CREATED)
以上是如何將 CSV 檔案上傳到 DJANGO REST的詳細內容。更多資訊請關注PHP中文網其他相關文章!