2013-02-28 12 views
25

Nach dem Speichern des Modells 'Produkte' möchte ich, dass das hochgeladene Bild genauso benannt wird wie zB pk 22.png oder 34.gif Ich möchte das Format nicht ändern das Bild nur der Name. Wie kann das gemacht werden? so weit unter Beispiel meines Modells ...Django ImageField Dateiname beim Hochladen ändern

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") 

Antwort

57

Sie können eine Funktion in upload_to Feld passieren:

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 

Meine Vorschläge einen zufälligen Dateinamen anstelle von {pk}.{ext} zurückkehren würde. Als Bonus wird es sicherer.

Was passiert ist, dass Django diese Funktion aufrufen wird, um festzustellen, wohin die Datei hochgeladen werden soll. Das bedeutet, dass Ihre Funktion für die Rückgabe des gesamten Pfads der Datei einschließlich des Dateinamens verantwortlich ist. Im Folgenden wird Funktion geändert, wo Sie wo zum Hochladen angeben können und wie man es benutzt:

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

schlug mich auf die Funktion :( –

+0

Tut mir leid. Ich habe eigentlich keine Antwort sehen. Auch wenn ich gepostet Mine bemerkt, dass es eine andere Antwort war ... – miki725

+0

die Instanz wäre, dass das Modell sein, übergeben wird? – jason

5

Sie können die Zeichenfolge Ihre Zuordnung zu upload_to mit einem abrufbaren ersetzen, wie in den docs beschrieben. Ich vermute jedoch, dass der Primärschlüssel möglicherweise nicht verfügbar ist, wenn der Parameter upload_to verwendet wird.

16

Django 1.7 und neuere nicht Migration mit Funktion wie diese machen. Basierend auf Antwort von @ miki275 und this Ticket, müssen Sie Ihre Funktion wie folgt machen:

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

Dies funktioniert auch mit Python 2.7 (Tested Django 1.9), während die angenommene Antwort nur mit> = 3.0 funktioniert Bitte beachten Sie, dass Sie aufgrund von Python 2-Einschränkungen keine ungebundenen Methodenfunktionen serialisieren können (z. B. eine Methode, die im selben Klassenkörper deklariert und verwendet wird).Bitte verschieben Sie die Funktion in den Hauptmodulkörper, um Migrationen zu verwenden. Weitere Informationen finden Sie unter https: // docs.djangoproject.com/de/1.9/topics/migrations/# serializing-values' – dotcomly

0

Eine weitere Möglichkeit, wie im Anschluss an diese Antwort https://stackoverflow.com/a/15141228/3445802, fanden wir das Problem, wenn wir Pfad zurückkehren müssen mit %Y/%m/%d, Beispiel:

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

so, wir behandeln es mit diesem:

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

Makesur e Das Modul time wurde importiert.

Verwandte Themen