So importieren Sie CSV-Daten in Django-Modelle

76

Ich habe einige CSV-Daten und möchte anhand der Beispiel-CSV-Daten in Django-Modelle importieren:

1;"02-01-101101";"Worm Gear HRF 50";"Ratio 1 : 10";"input shaft, output shaft, direction A, color dark green";
2;"02-01-101102";"Worm Gear HRF 50";"Ratio 1 : 20";"input shaft, output shaft, direction A, color dark green";
3;"02-01-101103";"Worm Gear HRF 50";"Ratio 1 : 30";"input shaft, output shaft, direction A, color dark green";
4;"02-01-101104";"Worm Gear HRF 50";"Ratio 1 : 40";"input shaft, output shaft, direction A, color dark green";
5;"02-01-101105";"Worm Gear HRF 50";"Ratio 1 : 50";"input shaft, output shaft, direction A, color dark green";

Ich habe einige Django-Modelle namens Product. In Artikel gibt es einige Felder wie name, descriptionund price. Ich möchte so etwas:

product=Product()
product.name = "Worm Gear HRF 70(02-01-101116)"
product.description = "input shaft, output shaft, direction A, color dark green"
product.price = 100
kleiner Fisch
quelle
1
< docs.python-tablib.org/en/latest/index.html > ist auch dafür eine erstaunliche Bibliothek.
Craig Labenz

Antworten:

83

Sie möchten das CSV-Modul verwenden, das Teil der Python-Sprache ist, und Sie sollten die Methode get_or_create von Django verwenden

 with open(path) as f:
        reader = csv.reader(f)
        for row in reader:
            _, created = Teacher.objects.get_or_create(
                first_name=row[0],
                last_name=row[1],
                middle_name=row[2],
                )
            # creates a tuple of the new object or
            # current object and a boolean of if it was created

In meinem Beispiel hat der Modelllehrer drei Attribute: Vorname, Nachname und zweiter Vorname.

Django-Dokumentation der Methode get_or_create

Friendm1
quelle
Danke für die Antwort. Stellen Sie zum Hinzufügen sicher, dass Sie die Kopfzeile überspringen, falls Sie eine haben. Wenn Sie es nicht ignorieren, kann dies zu schwer zu debuggenden Fehlern führen: stackoverflow.com/questions/43114679/…
Anupam
2
Um dies hinzuzufügen, habe ich dies über einen Verwaltungsbefehl getan und konnte den Import mit der Datei django manage.py ausführen:python manage.py loadgamecsv CSV_PATH
Rocco
Danke für die Antwort. Ich habe versucht, es in einem unabhängigen .py-Skript zu implementieren, aber dann stoße
Tms91
33

Wenn Sie eine Bibliothek verwenden möchten, eine schnelle Google - Suche nach csvund djangozeigt zwei Bibliotheken - django-Csvimport und django-Adapter . Lesen wir, was sie über sich zu sagen haben ...

  • Django-Adapter :

Der Django-Adapter ist ein Tool, mit dem Sie eine CSV / XML-Datei einfach in ein Python-Objekt oder eine Django-Modellinstanz umwandeln können.

  • django-importcsv :

django-csvimport ist ein generisches Importer-Tool, mit dem CSV-Dateien zum Auffüllen von Daten hochgeladen werden können.

Beim ersten müssen Sie ein Modell schreiben, das mit der CSV-Datei übereinstimmt, während beim zweiten Modell eher ein Befehlszeilenimporter verwendet wird. Dies ist ein großer Unterschied in der Art und Weise, wie Sie mit ihnen arbeiten, und jedes Modell eignet sich für einen anderen Projekttyp.

Also welches? Das hängt davon ab, welche davon auf lange Sicht besser für Ihr Projekt geeignet sind.

Sie können eine Bibliothek jedoch auch ganz vermeiden, indem Sie Ihr eigenes Django-Skript schreiben, um Ihre CSV- Datei zu importieren.

# open file & create csvreader
import csv, yada yada yada

# import the relevant model
from myproject.models import Foo

#loop:
for line in csv file:
     line = parse line to a list
     # add some custom validation\parsing for some of the fields

     foo = Foo(fieldname1=line[1], fieldname2=line[2] ... etc. )
     try:
         foo.save()
     except:
         # if the're a problem anywhere, you wanna know about it
         print "there was a problem with line", i 

Es ist super einfach. Zum Teufel, Sie können es interaktiv über die Django-Shell tun, wenn es sich um einen einmaligen Import handelt. Stellen Sie einfach fest, was Sie mit Ihrem Projekt tun möchten, wie viele Dateien Sie verarbeiten müssen, und versuchen Sie dann, herauszufinden, welche Bibliothek Ihren Anforderungen besser entspricht, wenn Sie sich für eine Bibliothek entscheiden .

Yuvi
quelle
Zu Ihrer
Information
2
@ Shog9 Das habe ich erst jetzt bemerkt. Ich verstehe es nicht, warum? Diese beiden Fragen hängen überhaupt nicht zusammen, und dies macht meine gesamte Antwort zu einer unsinnigen Erklärung für etwas völlig anderes als das, was das OP verlangt. Sollte es nicht vielleicht umgekehrt zusammengeführt werden?
Yuvi
Beide Fragen befassen sich mit demselben Problem, aber dies ist eine bessere Frage, um anderen ein Beispiel zu geben. Wenn es Ihnen nichts ausmacht, zu bearbeiten, kann Ihre Antwort hier hilfreich sein.
Shog9
@ Shog9 ok, ich verstehe deinen Standpunkt. Es macht mir nichts aus zu bearbeiten, ich werde es tun, wenn ich kann. Vielen Dank für die Antwort
Yuvi
13
"eine schnelle Google-Suche nach CSV und Django" ... brachte mich auf diese Seite :-p
Chris Huang-Leaver
8

Die Python- CSV-Bibliothek kann Ihre Analyse durchführen und Ihr Code kann sie in übersetzen Products().

msw
quelle
8

Sie können auch Django-Adapter verwenden

>>> from adaptor.model import CsvModel
>>> class MyCSvModel(CsvModel):
...     name = CharField()
...     age = IntegerField()
...     length = FloatField()
...
...     class Meta:
...         delimiter = ";"

Sie deklarieren ein MyCsvModel, das mit einer CSV-Datei wie folgt übereinstimmt:

Anthony, 27; 1,75

Um die Datei oder ein iterierbares Objekt zu importieren, gehen Sie einfach wie folgt vor:

>>> my_csv_list = MyCsvModel.import_data(data = open("my_csv_file_name.csv"))
>>> first_line = my_csv_list[0]
>>> first_line.age
    27

Ohne explizite Deklaration werden Daten und Spalten in derselben Reihenfolge abgeglichen:

Anthony --> Column 0 --> Field 0 --> name
27      --> Column 1 --> Field 1 --> age
1.75    --> Column 2 --> Field 2 --> length
mmrs151
quelle
Kennen Sie die Methode zum Korrigieren des Aktualisierungsarguments in der Meta-Klasse in meinem Csv-Modell? Ich versuche es, aber ich habe einen KeyError.
Cristian Rojas
7

etwas wie das:

f = open('data.txt', 'r')  
for line in f:  
   line =  line.split(';')  
   product = Product()  
   product.name = line[2] + '(' + line[1] + ')'  
   product.description = line[4]  
   product.price = '' #data is missing from file  
   product.save()  

f.close()  
DrDee
quelle
7

Verwenden Sie die Pandas-Bibliothek , um einen Datenrahmen für die CSV-Daten zu erstellen.
Benennen Sie die Felder, indem Sie sie entweder in die erste Zeile der CSV-Datei oder in den Code mithilfe der Spaltenmethode des Datenrahmens aufnehmen.
Erstellen Sie dann eine Liste der Modellinstanzen.
Verwenden Sie abschließend die django-Methode .bulk_create () , um Ihre Liste der Modellinstanzen an die Datenbanktabelle zu senden.

Die Funktion read_csv in Pandas eignet sich hervorragend zum Lesen von CSV-Dateien und bietet Ihnen viele Parameter zum Überspringen von Zeilen, Auslassen von Feldern usw.

import pandas as pd

tmp_data=pd.read_csv('file.csv',sep=';')
#ensure fields are named~ID,Product_ID,Name,Ratio,Description
#concatenate name and Product_id to make a new field a la Dr.Dee's answer
products = [
    Product(
        name = tmp_data.ix[row]['Name'] 
        description = tmp_data.ix[row]['Description'],
        price = tmp_data.ix[row]['price'],
    )
    for row in tmp_data['ID']
]
Product.objects.bulk_create(products)

Ich habe die Antwort von mmrs151 verwendet, aber das Speichern jeder Zeile (Instanz) war sehr langsam und alle Felder, die das Begrenzungszeichen enthalten (auch innerhalb von Anführungszeichen), wurden von der Methode open () - line.split (';') nicht behandelt.

Pandas hat so viele nützliche Vorbehalte, dass es sich lohnt, sie kennenzulernen

Erik
quelle
6

Für Django 1.8, das ich benutze,

Ich habe einen Befehl erstellt, mit dem Sie Objekte in Zukunft dynamisch erstellen können. Sie können also einfach den Dateipfad der CSV, den Modellnamen und den App-Namen der entsprechenden Django-Anwendung eingeben und das relevante Modell füllen, ohne das Feld anzugeben Namen. Wenn wir zum Beispiel die nächste CSV nehmen:

field1,field2,field3
value1,value2,value3
value11,value22,value33

Es werden die Objekte [{Feld1: Wert1, Feld2: Wert2, Feld3: Wert3}, {Feld1: Wert11, Feld2: Wert22, Feld3: Wert33}] für den Modellnamen erstellt, den Sie in den Befehl eingeben.

der Befehlscode:

from django.core.management.base import BaseCommand
from django.db.models.loading import get_model
import csv


class Command(BaseCommand):
    help = 'Creating model objects according the file path specified'

    def add_arguments(self, parser):
        parser.add_argument('--path', type=str, help="file path")
        parser.add_argument('--model_name', type=str, help="model name")
        parser.add_argument('--app_name', type=str, help="django app name that the model is connected to")

    def handle(self, *args, **options):
        file_path = options['path']
        _model = get_model(options['app_name'], options['model_name'])
        with open(file_path, 'rb') as csv_file:
            reader = csv.reader(csv_file, delimiter=',', quotechar='|')
            header = reader.next()
            for row in reader:
                _object_dict = {key: value for key, value in zip(header, row)}
                _model.objects.create(**_object_dict)

Beachten Sie, dass möglicherweise in späteren Versionen

from django.db.models.loading import get_model

ist veraltet und muss geändert werden

from django.apps.apps import get_model
DorZ
quelle
4

Sie können das Paket django-csv-importer verwenden. http://pypi.python.org/pypi/django-csv-importer/0.1.1

Es funktioniert wie ein Django-Modell

MyCsvModel(CsvModel):
    field1 = IntegerField()
    field2 = CharField()
    etc

    class Meta:
        delimiter = ";"
        dbModel = Product

Und Sie müssen nur: CsvModel.import_from_file ("meine Datei")

Dadurch werden Ihre Produkte automatisch erstellt.

trez
quelle
4
django-csv-importer wird nicht mehr zugunsten von django-
adaptern
4

Wenn Sie mit neuen Versionen von Django (> 10) arbeiten und keine Zeit mit dem Schreiben der Modelldefinition verbringen möchten. Sie können das Tool ogrinspect verwenden.

Dadurch wird eine Codedefinition für das Modell erstellt.

python manage.py ogrinspect [/path/to/thecsv] Product

Die Ausgabe ist die Klassen- (Modell-) Definition. In diesem Fall heißt das Modell Produkt . Sie müssen diesen Code in Ihre Datei models.py kopieren.

Anschließend müssen Sie (in der Shell) die neue Produkttabelle migrieren mit:

python manage.py makemigrations
python manage.py migrate

Weitere Informationen finden Sie hier: https://docs.djangoproject.com/de/1.11/ref/contrib/gis/tutorial/

Beachten Sie, dass das Beispiel für ESRI Shapefiles erstellt wurde, aber auch mit Standard-CSV-Dateien ziemlich gut funktioniert.

Zum Aufnehmen Ihrer Daten (im CSV-Format) können Sie Pandas verwenden.

import pandas as pd
your_dataframe = pd.read_csv(path_to_csv)
# Make a row iterator (this will go row by row)
iter_data = your_dataframe.iterrows()

Jetzt muss jede Zeile in ein Wörterbuch umgewandelt werden und dieses Diktat zum Instanziieren Ihres Modells verwenden (in diesem Fall Product ()).

# python 2.x
map(lambda (i,data) : Product.objects.create(**dict(data)),iter_data

Fertig, überprüfen Sie jetzt Ihre Datenbank.

Juan
quelle
2

Sie können versuchen, Django-Import-Export . Es hat eine nette Admin-Integration, ändert die Vorschau, kann Objekte erstellen, aktualisieren und löschen.

r_black
quelle
Zu Ihrer
Information
Es ist sehr einfach zu installieren und zu konfigurieren und kann nicht nur CSV, sondern auch XLSX, XLS usw. lesen. Dies ist sehr nützlich, da der Datenimport mit CSV wahrscheinlich fehlschlägt, wenn der Text Sonderzeichen enthält.
Tms91
2

Dies basiert auf Eriks Antwort von früher , aber ich fand es am einfachsten, die CSV-Datei mit Pandas einzulesen und dann für jede Zeile im In-Datenrahmen eine neue Instanz der Klasse zu erstellen.

Dieses Beispiel wird aktualisiert Verwendung ilocals pandasnicht mehr verwendet in der neuesten Version ix. Ich weiß nichts über Eriks Situation, aber Sie müssen die Liste außerhalb der for-Schleife erstellen, sonst wird sie nicht an Ihr Array angehängt, sondern einfach überschrieben.

import pandas as pd
df = pd.read_csv('path_to_file', sep='delimiter')
products = []
for i in range(len(df)):
    products.append(
        Product(
        name=df.iloc[i][0]
        description=df.iloc[i][1]
        price=df.iloc[i][2]
        )
    )
Product.objects.bulk_create(products)

Dies zerlegt lediglich den DataFrame in ein Array von Zeilen und wählt dann jede Spalte aus diesem Array aus dem Nullindex aus. (dh Name ist die erste Spalte, Beschreibung die zweite usw.)

Hoffentlich hilft das.

Drawson
quelle
1

Hier ist ein Django-Ei dafür:

django-csvimport

Andy Boot
quelle
1

Erwägen Sie die Verwendung der in Django integrierten Deserialisierer. Die Dokumente von Django sind gut geschrieben und können Ihnen den Einstieg erleichtern. Konvertieren Sie Ihre Daten von CSV in XML oder JSON und verwenden Sie einen Deserializer, um die Daten zu importieren. Wenn Sie dies über die Befehlszeile tun (und nicht über eine loaddataWebanforderung ), ist der Befehl manage.py besonders hilfreich.

Dave
quelle
Zu Ihrer
Information
1

Definieren Sie die Klasse in models.py und eine Funktion darin.

class all_products(models.Model):
    def get_all_products():
        items = []
        with open('EXACT FILE PATH OF YOUR CSV FILE','r') as fp:
            # You can also put the relative path of csv file
            # with respect to the manage.py file
            reader1 = csv.reader(fp, delimiter=';')
            for value in reader1:
                items.append(value)
        return items

Sie können auf das i-te Element in der Liste als Elemente zugreifen [i]

Pratik Gujarathi
quelle