django ImageField - как настроить имя + удалить старый файл

У меня есть модель с ImageField. Я уже установил upload_to и создал свой собственный класс FileSystemStorage для сохранения файла с уникальным именем... однако...

Эта настройка позволяет мне загружать и сохранять файл с уникальным именем для каждого файла (это нормально), но мне также нужно удалить предыдущий файл, который существовал, например.

Я загружаю file1.png, и он сохраняется как file1_xkdeujg.png (это просто случайная строка)

Затем я захожу в администратора django (используя интерфейс администратора django, поэтому нужно делать это через модель) и меняю изображение для этого поля на fileNEW.png

Что должно произойти сейчас:

1) он сохраняет новый файл как fileNEW_fjewiejk.png (уникальная случайная строка при каждом сохранении изображения) - готово

2) он сохраняет новый файл в базу данных - готово

3) удаляет старый файл - file1_xkdeuig.png - из файловой системы - не выполнено

В: Может ли кто-нибудь помочь мне с пунктом 3?

Некоторый код:

class Page(models.Model):
    image           = models.ImageField(upload_to='pages/', storage=MyFileSystemStorage())

И (позаимствовал большую часть этого кода откуда-то еще...):

class MyFileSystemStorage(FileSystemStorage):

    def get_valid_name(self, name):
            file_root, file_ext = os.path.splitext(name)
            return "%s_%s%s" % (file_root, rand_key(8), file_ext)

    def get_available_name(self, name):
            dir_name, file_name = os.path.split(name)
            file_root, file_ext = os.path.splitext(file_name)
            count = itertools.count(1)
            while self.exists(name):
                    name = os.path.join(dir_name, "%s_%s%s" % (rand_key(32),  count.next(), file_ext))
            return name

person Paul Johnston    schedule 18.03.2011    source источник


Ответы (2)


Ответ пришел из аналогичного вопроса на StackOverflow...

По сути, вы сохраняете исходное изображение в методе init, а затем проверяете, не изменилось ли оно перед сохранением.

После сохранения удалите изображение, хранящееся по исходному пути к изображению.

См. также этот ответ (ответ Джоша - тот, который я использовал и предпочитаю, поскольку он не попадает в базу данных).

Джанго: при сохранении, как вы можете проверить, изменилось ли поле?

person Paul Johnston    schedule 18.03.2011

Если я правильно понимаю, если вы переименуете файл, то файл будет дублироваться, а не перемещаться. Переопределение метода сохранения для класса Page может дать вам доступ к старому экземпляру и экземпляру росы. http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-model-methods

Все, что вам нужно сделать, это сохранить старое имя файла в переменной, после чего после вызова super.save() вы сможете os.system("rm "+path_to_file) в тех случаях, когда файл изменился. Это помогает?

person endre    schedule 18.03.2011
comment
Да - имеет смысл. Смотрите мой ответ для ссылки на ответ здесь, который я использовал. - person Paul Johnston; 18.03.2011
comment
Вместо os.system(rm +path) вы должны удалить файл напрямую с помощью os.remove(path). Если вы не проверяете свой ввод, вы можете позволить людям произвольно запускать любой код на вашем сервере. например что, если путь_к_файлу был установлен на image.png; rm -rf / ? Затем ваш сервер выполнит это. - person Rory; 29.09.2011
comment
Кроме того, это намного приятнее, так как использует вызовы стандартной библиотеки вместо разветвления оболочки и запуска команды. - person sleblanc; 07.02.2013