2014-09-10 5 views
22

Ich habe gerade meine App auf 1,7 hochgestuft (eigentlich immer noch versucht).Django - Ich kann keine Migrationen für ImageField mit dynamischem Wert für upload_to erstellen

Das ist, was ich in models.py hatte:

def path_and_rename(path): 
    def wrapper(instance, filename): 
     ext = filename.split('.')[-1] 
     # 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 

class UserProfile(AbstractUser): 
    #... 
    avatar = models.ImageField(upload_to=path_and_rename("avatars/"), 
           null=True, blank=True, 
           default="avatars/none/default.png", 
           height_field="image_height", 
           width_field="image_width") 

Wenn ich zu makemigrations versuchen, es wirft:

ValueError: Could not find function wrapper in webapp.models. 
Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared 
and used in the same class body). Please move the function into the main module body to use migrations. 

Antwort

48

Ich bin nicht sicher, ob es in Ordnung ist meine eigene Frage zu beantworten , aber ich habe gerade herausgefunden (denke ich).

Nach this bug report, herausgegeben ich meinen Code:

from django.utils.deconstruct import deconstructible 

@deconstructible 
class PathAndRename(object): 

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

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

path_and_rename = PathAndRename("/avatars") 

Und dann in Felddefinition:

avatar = models.ImageField(upload_to=path_and_rename, 
           null=True, blank=True, 
           default="avatars/none/default.png", 
           height_field="image_height", 
           width_field="image_width") 

Das ist für mich gearbeitet.

+0

Ich denke, das ist die richtige Lösung. –

+0

Ist es möglich, dies zu verwenden und einen benutzerdefinierten Dateipfad für jedes Feld hinzuzufügen? –

+0

@ Garreth00 Ja, übergeben Sie den Dateipfad als Parameter an die 'PathAndRename' Klasse. wie: 'custom_path = PathAndRename ("/profiles/bg-images ")' – alix

3

hatte ich das gleiche Problem, aber ich habe viele Imagefile in meinen Modellen

head = ImageField(upload_to=upload_to("head") 
icon = ImageField(upload_to=upload_to("icon") 
...etc 

Ich will nicht upload_to wraper func für jede Spalte Imagefield Ich habe erstellen.

So schaffe ich nur eine func namens Wrapper und freigegegeben

def wrapper(): 
    return 

Ich denke, es ist ganz gut funktioniert, weil ich Migrationsdatei geöffnet und ich fand diese:

('head', models.ImageField(upload_to=wrapper)), 

I denke, es ist kein Effekt Migrationsprozess

Verwandte Themen