freakydog: Überschreiben hochgeladener Dateien

Überschreiben hochgeladener Dateien

Wird eine Datei für ein FileField oder ImageField hochgeladen und exisitiert bereits, überschreibt Django diese Datei nicht sondern hängt einen Tiefstrich an die Datei. Die ältere Datei bleibt ohne Verweis im Dateisystem bestehen.

Überschreibst du also eine Datei rechnung.pdf drei mal, entsteht eine lustige Kaskade im Dateisystem.

  • rechnung.pdf
  • rechnung_.pdf
  • rechnung__.pdf
  • rechnung___.pdf (Der Pfad zu dieser Datei wird im FileField gespeichert)

Es ist nicht immer im Interesse, diese alten Dateien zu behalten. Sei es aus Platzmangel, Datenschutzgründen oder weil man einfach nur Ordnung auf seinem System halten will.

Derzeit gibt es keinen direkten Weg, das überschreiben zu erzwingen. Es gibt schon seit längerer Zeit ein Ticket im Django-Repository aber es schaut nicht so aus, als ob es in Django 1.1 eingespielt wird.

Automatisches Übeschreiben mit einem Custom-Storage ###

Hochgeladene Dateien werden von einem eigenen Modul, dem FileSystemStorage verarbeitet. Es öffnet und speichert die Dateien und prüft, ob der Dateiname schon exisitiert und hängt ggf. einen Tiefstrich an die Datei. Das passiert in der Methode get_available_name. Genau diese ist der Ansatzpunkt um das Überschreiben zu erzwingen.

Hier wird ein eigenes Storage erstellt aber vor dem Speichern der Datei, wird (wenn sie existiert) die alte Datei gelöscht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from django.db import models
from django.core.files.storage import FileSystemStorage

class OverwriteFileSystemStorage(FileSystemStorage):
    def get_available_name(self, name):
        if self.exists(name):
            self.delete(name)
        return name

class Invoice(models.Model):
    title = models.CharField(max_length=120)
    invoice = models.FileField(upload_to=upload_invoice, storage=OverwriteFileSystemStorage())

    def __unicode__(self):
        return self.title

Das Custom-Storage wird dem FileField oder dem ImageField als Attribut storage übergeben. Soll dieses Schema für alle Uploads gelten, ändere in der settings.py den Wert DEFAULT_FILE_STORAGE Standardmässig wird das oben genannte FileSystemStorage verwendet.

1
2
3
4
5
# Original
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'

# Immer alle Dateien überschreiben
DEFAULT_FILE_STORAGE = 'path.to.OverwriteFileSystemStorage'

Den originalen Dateinamen zusätzlich speichern

Dass Dateien nicht grundsätzlich überschrieben werden ist ja grundsätzlich keine schlechte Idee. Schließlich hat man immer ein automatisches Backup aller Änderungen. Lassen wir das Schema so wie es ist aber speichern wir den originalen Dateinamen zusätzlich in einem eigenen Feld. So können wir dem User später den orignalen Dateinamen anzeigen, im Dateisystem bleiben aber alle überschriebenen Dateien erhalten.

Ein upload-Callable ist ein schneller und sicherer Weg, dies zu erreichen. Mehr dazu hatte ich schon in Ordnung im Medienordner geschrieben.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from django.db import models

class Invoice(models.Model):

    def upload_invoice(instance, filename):
        instance.invoice_orig_filename = filename
        return filename

    title = models.CharField(max_length=120)
    invoice = models.FileField(upload_to=upload_invoice, storage=OverwriteFileSystemStorage())
    invoice_orig_filename = models.CharField(max_length=100, blank=True)

    def __unicode__(self):
        return self.title

Dateien löschen

Der Vollständigkeit halber: Von Haus aus ist es im Admin noch nicht möglich, hochgeladene Dateien wieder zu löschen. Stephan Jäkel hat ein Admin-Widget konstruiert, dass Dateien auf Klick wieder löscht.

Geschrieben am: 09. April 2009 um 12:44 Uhr, Abgelegt in Django & Python

Kommentare zu diesem Artikel (2):

  1. flosch schrieb am 09. April 2009:

    Dein zweiter Beitrag innerhalb von 24 Stunden - du willst wohl Mitarbeiter des Monats werden Smiley:  :) Wie immer, toller und hilfreicher Beitrag, danke!

  2. nicole schrieb am 02. Mai 2009:

    Danke,

    die Striche waren mir scho immer ein Dorn im Auge...

    Bye Nicole (sms-puls.de)

Kommentar schreiben

Kommentar hinzufügen

Neue Kommentare sind nur noch über diese Seite möglich.