Heim > Backend-Entwicklung > Python-Tutorial > SO LADEN SIE EINE CSV-DATEI AUF DJANGO REST HOCH

SO LADEN SIE EINE CSV-DATEI AUF DJANGO REST HOCH

DDD
Freigeben: 2024-11-05 19:25:02
Original
805 Leute haben es durchsucht

Das Hochladen einer CSV-Datei in Django REST (insbesondere in einer atomaren Umgebung) ist eine einfache Aufgabe, hat mich aber verwirrt, bis ich einige Tricks herausgefunden habe, die ich mit Ihnen teilen möchte.
In diesem Artikel verwende ich Postman (anstelle eines Frontends) und erkläre auch, was Sie bei Postman für den Anforderungsversand über Bilder einstellen müssen.

Was wir uns wünschen

  1. CSV über Django Rest in die Datenbank hochladen
  2. Machen Sie den Vorgang atomar, d. h. jeder Fehler in einer Zeile aus der CSV-Datei sollte ein vollständiges Rollback des gesamten Vorgangs zur Folge haben, sodass wir den Stress beim Ausschneiden der CSV-Datei vermeiden können, d. h. die Mühe, den Teil der Zeilen zu identifizieren, in den sie gelangt ist die DB und diejenigen, die aufgrund eines Fehlers auf halbem Weg nicht funktionierten!! (Teileintrag). Wir wollen also eine Alles-oder-Nichts-Sache!!

Methode

  1. Angenommen, Sie haben Django und Django REST bereits installiert, wäre der erste Schritt die Installation von Pandas, einer Python-Bibliothek zur Datenbearbeitung.

pip install pandas

  1. Weiter in Postman: Wählen Sie auf der Registerkarte „Text“ die Formulardaten aus und fügen Sie einen Schlüssel (einen beliebigen Namen) hinzu. Bewegen Sie den Mauszeiger in derselben Zelle ganz rechts in die Zelle und verwenden Sie das Dropdown-Menü, um die Option von „Text“ in „Datei“ zu ändern. Sobald Sie dies tun, setzt Postman den Inhaltstyp in den Kopfzeilen automatisch auf „multipart/form-data“.

Klicken Sie für die Wertzelle auf die Schaltfläche „Dateien auswählen“ und laden Sie die CSV-Datei hoch. Schauen Sie sich den Screenshot unten an

HOW TO UPLOAD A CSV FILE TO DJANGO REST

Stellen Sie unter „Headers“ Content-Disposition und den Wert auf „form-data“ ein. name="Datei"; Dateiname="Ihr_Dateiname.csv". Ersetzen Sie your_file_name.csv durch Ihren tatsächlichen Dateinamen. Schauen Sie sich den Screenshot unten an.

HOW TO UPLOAD A CSV FILE TO DJANGO REST

  1. In den Django-Ansichten lautet der Code wie folgt:
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)

Nach dem Login kopieren
Nach dem Login kopieren

Erklärung des obigen Codes:
Der Code beginnt mit dem Importieren notwendiger Pakete, dem Definieren einer klassenbasierten Ansicht und dem Festlegen einer Parser-Klasse (FileUploadParser). Der erste Teil der Post-Methode in der Klasse versucht, die Datei von request.FILES abzurufen und ihre Verfügbarkeit zu überprüfen.
Anschließend überprüft eine kleine Validierung, ob es sich um eine CSV-Datei handelt, indem die Erweiterung überprüft wird.
Der nächste Teil lädt es in einen Pandas-Datenrahmen (ähnlich einer Tabellenkalkulation):
df = pd.read_csv(csv_file, delimiter=',',skiprows=3,dtype=str).iloc[:-1]
Ich werde einige der an die Ladefunktion übergebenen Argumente erläutern:

Skiprows
Beim Lesen der geladenen CSV-Datei ist zu beachten, dass die CSV-Datei in diesem Fall über ein Netzwerk übertragen wird, sodass einige Metadaten wie Dinge am Anfang und Ende der Datei hinzugefügt werden. Diese Dinge können ärgerlich sein und liegen nicht im CSV-Format (Comma Separated Value) vor, sodass sie beim Parsen tatsächlich zu Fehlern führen können. Dies erklärt, warum ich „skiprows=3“ verwendet habe, um die ersten drei Zeilen mit Metadaten und Header zu überspringen und direkt im Hauptteil der CSV-Datei zu landen. Wenn Sie Skiprows entfernen oder eine geringere Zahl verwenden, erhalten Sie möglicherweise eine Fehlermeldung wie: Fehler bei der Tokenisierung der Daten. C-Fehler, sonst bemerken Sie möglicherweise, dass die Daten ab der Kopfzeile beginnen.

dtype=str
Pandas erweist sich gerne als schlau, wenn es darum geht, den Datentyp bestimmter Spalten zu erraten. Ich wollte alle Werte als String haben, also habe ich dtype=str

verwendet

Trennzeichen
Gibt an, wie die Zellen getrennt werden. Der Standardwert ist normalerweise Komma.

iloc[:-1]
Ich musste iloc verwenden, um den Datenrahmen aufzuteilen und die Metadaten am Ende des df zu entfernen.

Dann konvertiert die nächste Zeile df = df.where(pd.notnull(df), None) alle NaN-Werte in None. NaNi ist ein Ersatzwert, den Pandas verwendet, um None darzustellen.

Der nächste Block ist etwas knifflig. Wir durchlaufen jede Zeile im Datenrahmen, instanziieren die Zeilendaten mit dem BiodataModel, führen eine Validierung auf Modellebene (nicht auf Serialisierungsebene) mit der Methode full_clean() durch, da die Massenerstellung die Django-Validierung umgeht, und fügen dann unsere Erstellungsvorgänge einer Liste mit dem Namen „ bulk_data. Ja, hinzufügen noch nicht ausgeführt! Denken Sie daran, dass wir versuchen, eine atomare Operation (auf Batch-Ebene) durchzuführen, also wollen wir „all“ oder „None“. Das einzelne Speichern von Zeilen führt nicht zu einem All-oder-Keine-Verhalten.

Dann zum letzten wichtigen Teil. Innerhalb eines Transaction.atomic()-Blocks (der alles oder kein Verhalten bereitstellt) führen wir BiodataModel.objects.bulk_create(bulk_data) aus, um alle Zeilen auf einmal zu speichern.

Noch etwas. Beachten Sie die Indexvariable und den Except-Block in der for-Schleife. In der Ausnahmeblock-Fehlermeldung habe ich 2 zur von df.iterrows() abgeleiteten Indexvariablen hinzugefügt, da der Wert bei Betrachtung in einer Excel-Datei nicht genau mit der Zeile übereinstimmte, in der er sich befand. Der Ausnahmeblock fängt jeden Fehler ab und erstellt beim Öffnen in Excel eine Fehlermeldung mit der genauen Zeilennummer, sodass der Uploader die Zeile in der Excel-Datei leicht finden kann!

Danke fürs Lesen!!!

VERSIONEN DER VERWENDETEN WERKZEUGE

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)

Nach dem Login kopieren
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonSO LADEN SIE EINE CSV-DATEI AUF DJANGO REST HOCH. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage