2010-04-20 20 views
42

Qual è il modo migliore per rinominare le foto con un nome file univoco sul server mentre vengono caricate, usando django? Voglio assicurarmi che ogni nome venga usato una sola volta. Esistono app per il pinax che possono farlo, forse con GUID?Applicare nomi di file di caricamento univoci utilizzando django?

+0

Hai bisogno di una libreria di python per rinominare i file, quindi sono unici? – Aurril

+0

sì, è la mia media – zjm1126

risposta

109

Utilizzare uuid. Per legarlo al modello, vedi Django documentation per FileField upload_to.

Ad esempio nella tua models.py definire la seguente funzione:

import uuid 
import os 

def get_file_path(instance, filename): 
    ext = filename.split('.')[-1] 
    filename = "%s.%s" % (uuid.uuid4(), ext) 
    return os.path.join('uploads/logos', filename) 

Poi, al momento di definire il tuo FileField/ImageField, specificare get_file_path come valore upload_to.

file = models.FileField(upload_to=get_file_path, 
         null=True, 
         blank=True, 
         verbose_name=_(u'Contact list')) 
+1

Questa è una decisione sbagliata per farlo in questo modo, poiché avrai una migrazione infinita su questi campi, poiché in ogni migrazione avrai un percorso di caricamento diverso. –

+6

@Creotiv Questo non sta cambiando il percorso di upload, sta sostituendo il nome file con un UUID. Questo non dovrebbe causare problemi di migrazione. – Hybrid

+0

@Hybrid Sì, ma a ogni migrazione, il percorso della directory sarà diverso, quindi il sistema di migrazione penserà che quel campo sia cambiato. –

0

Come concatenare il nome file con la data/ora in cui è stata caricata la foto e quindi utilizzare hashlib per creare un digest di messaggi? Questo dovrebbe darti nomi di file unici.

In alternativa è possibile riutilizzare a neat little snippet che crea nomi di file univoci e quindi utilizzare il percorso completo del file come input per la chiamata hash. Questo ti dà stringhe di lunghezza costante uniche che puoi mappare ai tuoi file.

+0

ma, come fare lo stesso nome quando è la stessa ora? – zjm1126

+1

È possibile aggiungere la quantità di spazio libero su disco nella stringa hash, che dovrebbe sempre cambiare quando si carica un nuovo file. –

+1

@ zjm1126 @Jon Cage potresti inventare ogni sorta di modi per renderlo più probabile che sia unico e tale, ma fondamentalmente ci sarà sempre una sorta di probabilità di collisioni e l'idea è solo quella di ridurre tale probabilità ad un ammontare accettabile e poi gestire quando succede –

5

Prima di Django 1.6.6, 1.5.9 e 1.4.14, la funzione get_avaialable_name assegnava automaticamente ai file un nome univoco aggiungendo un carattere di sottolineatura. Quindi, per esempio, se salvi un file "test.jpg" e poi un altro file, "test.jpg" sul tuo server, il primo sarà chiamato test.jpg, e il secondo sarà chiamato test_1.jpg.

Alas, che risulta essere un vettore per il DDOS di una macchina, inviandogli migliaia di file a zero byte da archiviare, ognuno dei quali controlla migliaia di file precedenti per vedere quale dovrebbe essere il suo nome.

Come per il numero see in the docs, il nuovo sistema aggiunge sette cifre casuali dopo il trattino basso per risolvere il problema.

4

Un modo migliore potrebbe essere utilizzare una classe comune in helpers.py. In questo modo puoi riutilizzare il generatore di file casuali nelle tue app.

Nel vostro helpers.py:

import os 
import uuid 
from django.utils.deconstruct import deconstructible 


@deconstructible 
class RandomFileName(object): 
    def __init__(self, path): 
     self.path = os.path.join(path, "%s%s") 

    def __call__(self, _, filename): 
     # @note It's up to the validators to check if it's the correct file type in name or if one even exist. 
     extension = os.path.splitext(filename)[1] 
     return self.path % (uuid.uuid4(), extension) 

E poi nel modello solo importare la classe helper:

from mymodule.helpers import RandomFileName 

E poi usarlo:

logo = models.ImageField(upload_to=RandomFileName('logos')) 

Rif: https://coderwall.com/p/hfgoiw/give-imagefield-uploads-a-unique-name-to-avoid-file-overwrites

0

Al momento della stesura di questa risposta sembra che non sia più necessario fare qualcosa di speciale per far sì che ciò accada. Se imposti un FileField con una proprietà upload_to statica, il sistema di archiviazione Django gestirà automaticamente i nomi in modo tale che se viene caricato un nome file duplicato, Django genererà casualmente un nuovo nome file univoco per il duplicato.

Lavori su Django 1.10.

Problemi correlati