Применять уникальные имена файлов загрузки с помощью django?

каков наилучший способ переименования фотографий с уникальным именем файла на сервере по мере их загрузки, используя django? Я хочу убедиться, что каждое имя используется только один раз. Есть ли какие-либо приложения pinax, которые могут это сделать, возможно, с GUID?

5 ответов


используйте uuid. Чтобы связать это с вашей моделью, см. документация Django для FileField upload_to.

например в вашем models.py определите следующую функцию:

import uuid
import os

def get_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    return os.path.join('uploads/logos', filename)

затем при определении поля FileField / ImageField укажите get_file_path как upload_to значение.

file = models.FileField(upload_to=get_file_path,
                        null=True,
                        blank=True,
                        verbose_name=_(u'Contact list'))

до Django 1.6.6, 1.5.9 и 1.4.14,get_avaialable_name функция автоматически даст файлам уникальное имя, добавив подчеркивание. Так, например, если вы сохраните один файл " test.jpg", а затем другой файл, " тест.jpg " на ваш сервер, первый будет называться test.jpg, а второй будет называться test_1.формат jpg.

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

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


лучший способ может использовать общий класс в вашем helpers.py - ... Таким образом, вы можете повторно использовать генератор случайных файлов в своих приложениях.

в вашем helpers.py:

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


@deconstructible
class RandomFileName(object):
    def __init__(self, path):
        self.path = os.path.join(path, "%s%s")

    def __call__(self, _, filename):
        # @note It's up to the validators to check if it's the correct file type in name or if one even exist.
        extension = os.path.splitext(filename)[1]
        return self.path % (uuid.uuid4(), extension)

а затем в вашей модели просто импортируйте вспомогательный класс:

from mymodule.helpers import RandomFileName 

и затем использовать его:

logo = models.ImageField(upload_to=RandomFileName('logos'))

Ref: https://coderwall.com/p/hfgoiw/give-imagefield-uploads-a-unique-name-to-avoid-file-overwrites


Как насчет объединения имени файла с датой / временем загрузки фотографии, а затем с помощью hashlib создать дайджест сообщения? Это должно дать вам уникальные имена.

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


на момент написания этого ответа, кажется, вам больше не нужно делать ничего особенного, чтобы это произошло. Если вы настроили поле FileField со статическим свойством upload_to, система хранения Django будет автоматически управлять именованием, так что при загрузке дубликата имени файла Django будет случайным образом генерировать новое уникальное имя файла для дубликата.

работает на Django 1.10.