CSV-Upload und Update in Django

Django, Flask, Bottle, WSGI, CGI…
Antworten
Rise Nexus
User
Beiträge: 1
Registriert: Mittwoch 30. Januar 2019, 13:09

Hi,

ich erstelle grad ein Programm welches einen CSV-Upload bereitstellt. Der Upload funktioniert im Grunde auch ganz gut (ich benutze hierfür die Django Funktion create()). Wenn ich nun einen Wert in der CSV-Datei änder, würde ich gerne beim erneuten Upload die derzeitigen Werte in der Datenbank mit den neuen überschreiben. Ich habe versucht die Django Funktion Model.objects.filter().update() zu verwenden , allerdings ohne Erfolg. Die Option die alte Tabelle zu löschen und die neue hochzuladen muss ich ausschließen auch wenn diese Möglichkeit im Grunde am einfachsten ist.
Für den Upload benutze ich den csv.reader, der die Datei zeilenweise einliest.
Hier ist mein Code für den Upload.

views.py

[/code]

Code: Alles auswählen

def file_upload(request): 
    if request.method == "POST":
        form = UploadFileForm(request.POST, request.FILES)
        count = 0
        if form.is_valid():
            csv_file = request.FILES['file']
            with open(str(csv_file)) as file:
                reader = csv.reader(file)
                for row in reader:
                    count += 1
                    ds1 = Excel1.objects.filter(id = count).values_list().exists()
                    #print("TEst", ds1)
                    try:
                        if not ds1:
                            _, p = Excel1.objects.create(gebaeudebereich=row[0], gebaeudenummer = row[1],
                                                    ebene = row[2], raum = row[3], dose= row[4],
                                                    switch_ip=row[5], switch_port=row[6], datum = row[7], akteur = row[8])
                            #print("Test2")
                        else:
                            _, h = Excel1.objects.filter(id = count).update(gebaeudebereich=row[0], gebaeudenummer = row[1],
                                                    ebene = row[2], raum = row[3], dose= row[4],
                                                    switch_ip=row[5], switch_port=row[6], datum = row[7], akteur = row[8])

                    except IntegrityError:
                        continue
                return redirect('testapp:index')
    form = UploadFileForm()
    return render(
    request, "testapp/file_upload.html", {"form": form}
    )
models.py

Code: Alles auswählen

class Excel1(models.Model):
    gebaeudebereich = models.CharField(max_length=100)
    gebaeudenummer = models.CharField(max_length=100)
    ebene = models.CharField(max_length=100)
    raum = models.CharField(max_length=100)
    dose = models.CharField(max_length=100)
    switch_ip = models.CharField(max_length=100)
    switch_port = models.CharField(max_length=100)
    datum = models.CharField(max_length=100)
    akteur = models.CharField(max_length=100)


    class Meta:
        unique_together = (('gebaeudebereich', 'gebaeudenummer', 'ebene', 'raum', 'dose'),('switch_ip', 'switch_port'))

meine Form Klasse

Code: Alles auswählen

class UploadFileForm(forms.Form):
    file = forms.FileField()
Also im Grunde würde ich gerne die CSV-Datei beliebig oft hochladen können und wenn Felder geändert wurden sollen diese überschrieben werden. Ich hänge an diesem Problem schon länger deswegen würde ich mich über jede Hilfe freuen.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Rise Nexus: Was heisst denn „ohne Erfolg“? Warum ist es okay `IntegrityError` im Grunde einfach so zu ignorieren? Warum bist Du so sicher das das mit der `id` so funktioniert, also das `create()`/die Datenbank sich an die Annahme hält, dass automatisch vergebene IDs denen entsprechen die Du im Programm mit `count` generierst?

`count` wird viel zu früh initialisiert. Eigentlich würde man da eher die `enumerate()`-Funktion für verwenden.

Der Modelname `Excel1` sowie das Model selbst sind ”komisch” – alle Felder sind vom Typ `Charfield`?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Aus Datenbanksicht wäre es gut, die statischen Größen von den sich ändernden zu trennen, also zumindest eine eigene Tabelle für Raum und/oder Dose.
Meine Empfehlung ist (fast) immer, gar keine Daten zu überschreiben. Für Änderungen der Zuordnung Dose <-> Switch also immer einen neuen Eintrag anzulegen.

Datum ist vom Typ her immer ein "TIMESTAMP WITH TIMEZONE", für IP-Addressen haben die meisten Datenbanken auch spezielle Datentypen. Wenn man mehr Informationen zu Akteuren speichern will, sollte das auch eine eigene Tabelle sein und der akteur hier nur eine ID.
Also datum, akteur_id, dose_id, switch_ip, switch_port.
Ob sich etwas geändert hat, findet man heraus, ob der Datensatz, der hinter dose_id geschspeichert ist noch der selbe ist. Das macht man nicht über eine händisch mitgezählte interne ID.
Antworten