Django: Как сохранить исходное имя файла в FileField?

Я хочу, чтобы имена файлов были случайными, и поэтому я использую функцию upload_to, которая возвращает случайное имя файла так:

from uuid import uuid4
import os
def get_random_filename(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (str(uuid4()), ext)
    return os.path.join('some/path/', filename)

# inside the model
class FooModel(models.Model):
    file = models.FileField(upload_to=get_random_filename)

Однако я хотел бы сохранить исходное имя файла в атрибуте внутри модели. Что-то вроде этого не работает:

def get_random_filename(instance, filename):
    instance.filename = filename
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (str(uuid4()), ext)
    return os.path.join('some/path/', filename)

# inside the model
class FooModel(models.Model):
    file = models.FileField(upload_to=get_random_filename)
    filename = models.CharField(max_length=128)

Как я могу это сделать?

Спасибо.

Ответ 1

Обычно опубликованный код работает, возможно, фактический код

class FooModel(models.Model):
    filename = models.CharField(max_length=128)
    file = models.FileField(upload_to=get_random_filename)

Обратите внимание на переключение порядка полей выше.

Это не будет работать, потому что upload_to() вызывается pre_save(), здесь в коде, когда фактическое значение из FileField. Вы могли обнаружить, что присвоение атрибуту filename в upload() происходит после генерации первого параметра filename во вставке sql. Таким образом, присваивание не вступает в силу в сгенерированном SQL и влияет только на сам экземпляр.

Если это не проблема, отправьте код, введенный в оболочку.

Ответ 2

Вы можете пойти по пути заполнения имени файла во время процесса сохранения. Очевидно, что вам нужно сохранить исходное имя файла в памяти, когда запускается get_random_filename.

# inside the model
class FooModel(models.Model):
    file = models.FileField(upload_to=get_random_filename)
    filename = models.CharField(max_length=128)

    def save(self, force_insert=False, force_update=False):
        super(FooModel, self).save(force_insert, force_update)
            #Do your code here...

Ответ 3

Просто переупорядочивайте свои команды. https://docs.djangoproject.com/en/dev/topics/db/models/

def save(self, *args, **kwargs):
        do_something()
        super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
        do_something_else()