@DmitrIvanov
Веб-разработка

Как изменять имя файла при загрузки в Django?

Как изменить имя файла при загрузки в Django на свое, желательно на UUID?
  • Вопрос задан
  • 2756 просмотров
Решения вопроса 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Django
Седой и строгий
from os.path import splitext
from uuid import uuid4
from django.core.files.storage import FileSystemStorage

class UUIDFileStorage(FileSystemStorage):
    def get_available_name(self, name, max_length=None):
        _, ext = path.splitext(name)
        return uuid4().hex + ext

class SomeModel(models.Model):
    some_filed = models.ImageField('Какое-то изображение', upload_to='someimages', storage=UUIDFileStorage())
Ответ написан
neatsoft
@neatsoft
Life is too short for bad software
Для именования файлов лучше использовать хэш, а не uuid. Это гарантирует уникальность имён, и обеспечивает дедупликацию данных: сколько бы раз пользователи не заливали файл с одинаковым содержимым, он будет храниться в единственном экземпляре (исключение - файлы с одинаковым содержимым и разными расширениями, но это разумный компромисс - работать с файлами без расширений менее удобно на многих этапах).

Можно реализовать соответствующую функциональность самостоятельно:

app_name/models.py:
import hashlib
import os

from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.db import models


def upload_to(instance, filename, fieldname):
    ext = os.path.splitext(filename)[1].lower()
    class_name = instance.__class__.__name__.lower()

    h = hashlib.sha256()
    field = getattr(instance, fieldname)
    for chunk in field.chunks():
        h.update(chunk)
    name = h.hexdigest()

    return os.path.join(
        class_name,
        name + ext,
    )


class OverwriteStorage(FileSystemStorage):
    def get_available_name(self, name, max_length=None):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name


class Article(models.Model):
    image = models.ImageField(
        storage=OverwriteStorage(),
        upload_to=lambda inst, fn: upload_to(inst, fn, 'image'),
    )


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

Установить hashedfilenamestorage:
pip install django-hashedfilenamestorage

и добавить следующую строку в settings.py:
DEFAULT_FILE_STORAGE = 'django_hashedfilenamestorage.storage.HashedFilenameFileSystemStorage'
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы