2013-02-28 14 views
25

Al salvataggio del modello 'Prodotti' Vorrei che l'immagine caricata fosse nominata come pk per esempio 22.png o 34.gif Non voglio cambiare il formato di l'immagine solo il nome. Come si può fare? esempio del mio modello in modo molto più in basso ...Django ImageField cambia il nome del file al caricamento

image = models.ImageField(
     upload_to="profiles", 
     height_field="image_height", 
     width_field="image_width", 
     null=True, 
     blank=True, 
     editable=True, 
     help_text="Profile Picture", 
     verbose_name="Profile Picture" 
    ) 
    image_height = models.PositiveIntegerField(null=True, blank=True, editable=False, default="100") 
    image_width = models.PositiveIntegerField(null=True, blank=True, editable=False, default="100") 

risposta

57

è possibile passare una funzione nel campo upload_to:

def f(instance, filename): 
    ext = filename.split('.')[-1] 
    if instance.pk: 
     return '{}.{}'.format(instance.pk, ext) 
    else: 
     pass 
     # do something if pk is not there yet 

I miei suggerimenti sarebbe quello di restituire un nome di file casuale invece di {pk}.{ext}. Come bonus, sarà più sicuro.

Quello che succede è che Django chiamerà questa funzione per determinare dove caricare il file. Ciò significa che la tua funzione è responsabile della restituzione dell'intero percorso del file incluso il nome del file.

import os 
from uuid import uuid4 

def path_and_rename(path): 
    def wrapper(instance, filename): 
     ext = filename.split('.')[-1] 
     # get filename 
     if instance.pk: 
      filename = '{}.{}'.format(instance.pk, ext) 
     else: 
      # set filename as random string 
      filename = '{}.{}'.format(uuid4().hex, ext) 
     # return the whole path to the file 
     return os.path.join(path, filename) 
    return wrapper 

FileField(upload_to=path_and_rename('upload/here/'), ...) 
+1

mi ha battuto alla funzione :( –

+0

dispiace. Io in realtà non ha visto la vostra risposta. Anche quando ho postato il mio notato che ci fosse un'altra risposta ... – miki725

+0

l'istanza viene passata quello sarebbe il modello? – jason

5

È possibile sostituire la stringa tua assegnazione ad upload_to con un richiamabile come descritto nel docs. Tuttavia, sospetto che la chiave primaria potrebbe non essere disponibile nel punto in cui viene utilizzato il parametro upload_to.

16

Django 1.7 e versioni successive non farà la migrazione con la funzione come questa: Qui di seguito è la funzione in cui è possibile specificare dove caricare e come usarlo modificato. Sulla base di risposta da @ miki275 e this biglietto, è necessario per rendere la vostra funzione come questa:

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

@deconstructible 
class UploadToPathAndRename(object): 

    def __init__(self, path): 
     self.sub_path = path 

    def __call__(self, instance, filename): 
     ext = filename.split('.')[-1] 
     # get filename 
     if instance.pk: 
      filename = '{}.{}'.format(instance.pk, ext) 
     else: 
      # set filename as random string 
      filename = '{}.{}'.format(uuid4().hex, ext) 
     # return the whole path to the file 
     return os.path.join(self.sub_path, filename) 

FileField(upload_to=UploadToPathAndRename(os.path.join(MEDIA_ROOT, 'upload', 'here'), ...) 
+0

Questo funziona anche con python 2.7 (Testato Django 1.9) mentre la risposta accettata funziona solo con> = 3.0 che genera l'errore ' Si noti che a causa delle limitazioni di Python 2, non è possibile serializzare le funzioni del metodo non associato (ad esempio un metodo dichiarato e utilizzato nello stesso corpo della classe).Si prega di spostare la funzione nel corpo del modulo principale per utilizzare le migrazioni. Per ulteriori informazioni, consultare https: // docs.djangoproject.com/it/1.9/topics/migrations/# serializing-values' – dotcomly

0

Un'altra opzione, come seguendo questa risposta https://stackoverflow.com/a/15141228/3445802, abbiamo trovato il problema quando abbiamo bisogno percorso tornare con %Y/%m/%d, ad esempio:

FileField(upload_to=path_and_rename('upload/here/%Y/%m/%d'), ...) 

così, gestiamo con questo:

FileField(upload_to=path_and_rename('upload/here/{}'.format(time.strftime("%Y/%m/%d"))), ...) 

Makesur e il modulo time è stato importato.

Problemi correlati