Memuat naik fail CSV ke Django REST (terutamanya dalam tetapan atom) adalah tugas yang mudah, tetapi membuatkan saya tertanya-tanya sehingga saya mengetahui beberapa helah yang akan saya kongsikan dengan anda.
Dalam artikel ini, saya akan menggunakan posmen (menggantikan bahagian hadapan) dan juga akan berkongsi perkara yang anda perlu tetapkan pada posmen untuk menghantar permintaan melalui gambar.
Apa yang kita inginkan
Kaedah
pip pasang panda
Untuk sel nilai, klik butang 'Pilih Fail' dan muat naik CSV. Semak tangkapan skrin di bawah
Di bawah pengepala, tetapkan Pelupusan Kandungan dan nilai kepada data bentuk; nama = "fail"; nama fail="nama_fail_anda.csv". Gantikan nama_fail anda.csv dengan nama fail sebenar anda. Semak tangkapan skrin di bawah.
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)
Menjelaskan kod di atas:
Kod ini bermula dengan mengimport pakej yang diperlukan, mentakrifkan pandangan berasaskan kelas dan menetapkan kelas parser (FileUploadParser). Bahagian pertama kaedah siaran dalam kelas cuba mendapatkan fail daripada request.FILES dan semak ketersediaannya.
Kemudian pengesahan kecil menyemak bahawa ia adalah CSV dengan menyemak sambungan.
Bahagian seterusnya memuatkannya ke dalam bingkai data panda (sangat mirip hamparan):
df = pd.read_csv(csv_file, delimiter=',',skiprows=3,dtype=str).iloc[:-1]
Saya akan menerangkan beberapa hujah yang dihantar kepada fungsi pemuatan:
kayuh ski
Dalam membaca fail csv yang dimuatkan, perlu diperhatikan bahawa csv dalam kes ini diluluskan melalui rangkaian, jadi beberapa metadata seperti bahan ditambahkan pada permulaan dan penghujung fail. Perkara ini boleh menjengkelkan dan bukan dalam bentuk nilai dipisahkan koma (csv) jadi sebenarnya boleh menimbulkan ralat dalam penghuraian. Ini menerangkan sebab saya menggunakan skiprows=3, untuk melangkau 3 baris pertama yang mengandungi metadata dan pengepala dan mendarat terus pada badan csv. Jika anda mengalih keluar skiprowatau menggunakan nombor yang lebih kecil, mungkin anda mungkin mendapat ralat seperti: Ralat token data. Ralat C atau anda mungkin melihat data bermula dari pengepala.
dtype=str
Panda suka membuktikan pintar dalam cuba meneka jenis data lajur tertentu. Saya mahukan semua nilai sebagai rentetan, jadi saya menggunakan dtype=str
pembatas
Menentukan cara sel dipisahkan. Lalai biasanya koma.
iloc[:-1]
Saya terpaksa menggunakan iloc untuk menghiris bingkai data, mengalih keluar metadata pada penghujung df.
Kemudian, baris seterusnya df = df.where(pd.notnull(df), None) menukar semua NaNvalues kepada None. NaNi ialah nilai tetap yang digunakan oleh panda untuk mewakili Tiada.
Blok seterusnya agak rumit. Kami menggelungkan setiap baris dalam bingkai data, membuat instantiate data baris dengan BiodataModel, melaksanakan pengesahan peringkat model (bukan peringkat serializer) dengan kaedah full_clean() kerana ciptaan pukal memintas pengesahan Django, dan kemudian menambah operasi ciptaan kami pada senarai yang dipanggil bulk_data. Ya , tambah belum jalan ! Ingat, kami cuba melakukan operasi atom (pada peringkat kelompok ) jadi kami mahu semua atau Tiada. Menyimpan baris secara individu tidak akan memberi kita semua atau tiada gelagat.
Kemudian untuk bahagian penting yang terakhir. Dalam blok transaction.atomic() (yang menyediakan semua atau tiada gelagat), kami menjalankan BiodataModel.objects.bulk_create(bulk_data) untuk menyimpan semua baris sekaligus.
Satu perkara lagi. Perhatikan pembolehubah indeks dan blok kecuali dalam gelung for. Dalam mesej ralat blok kecuali, saya menambah 2 pada pembolehubah indeks yang diperoleh daripada df.iterrows() kerana nilai itu tidak sepadan dengan baris yang dihidupkan, apabila dilihat dalam fail excel. Blok except menangkap sebarang ralat dan membina mesej ralat yang mempunyai nombor baris yang tepat apabila dibuka dalam excel, supaya pemuat naik dapat mengesan baris dalam fail excel dengan mudah!
Terima kasih kerana membaca!!!
VERSI ALAT YANG DIGUNAKAN
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)
Atas ialah kandungan terperinci BAGAIMANA UNTUK MUAT NAIK FAIL CSV KE DJANGO REST. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!