1. get_valid_filename — это что?



django.utils.text.get_valid_filename — это небольшая вспомогательная функция, которая превращает строки в безопасные для файловой системы имена файлов.
Она удаляет или заменяет запрещенные или проблемные символы (такие как слэши, управляющие символы и т. д.) в большинстве операционных систем, таких как Windows, macOS, Linux и нормализует строку в предсказуемый формат.

Зачем это нужно?
Когда пользователи загружают файлы или создают имена файлов из произвольного ввода (например, заголовок блога, теги пользователя), использование таких символов, как слэши (../etc/passwd), может привести к разрыву файловой системы или возникновению уязвимостей безопасности.


2. Как это работает

from django.utils.text import get_valid_filename

raw = "My: New/Project? 2024*"
safe = get_valid_filename(raw)
print(safe)   # → "My_New_Project_2024"

Основные действия

Ввод Результат Описание
"my file.txt" "my_file.txt" Пробел → подчеркивание
"../etc/passwd" "etc_passwd" Удален ведущий символ и слэш
"file<name>.txt" "file_name_.txt" Символы < и > заменены
" " "" Только пробелы приводят к пустой строке
"a"*300 "a"*255 Обрезка до предела файловой системы (255 символов)

Функция кроссплатформенная и допускает только безопасный набор символов ([A-Za-z0-9_.-]), остальные символы заменяются подчеркиванием (_).


3. Полезные ситуации



Ситуация Необходимость
Загрузка пользователем Предотвращение обхода директорий (../../etc/passwd) и запрещенных символов
Имена файлов на основе слогов Преобразование заголовка блога в имя файла для статического сайта
Экспорт данных Создание имен файлов CSV/JSON с учетом полей базы данных (запятые, кавычки и др.)
Автоматическое резервное копирование Создание имен файлов резервного копирования с временными отметками на основе произвольной строки

4. Практический пример: Сохранение загруженных изображений

# views.py
from django.shortcuts import render
from django.core.files.storage import default_storage
from django.utils.text import get_valid_filename

def upload_image(request):
    if request.method == 'POST':
        uploaded = request.FILES['image']
        # Очистка оригинального имени файла
        safe_name = get_valid_filename(uploaded.name)
        # При необходимости добавьте ID пользователя или временную метку
        final_name = f"{request.user.id}_{safe_name}"
        path = default_storage.save(f"uploads/{final_name}", uploaded)
        return render(request, 'success.html', {'path': path})
    return render(request, 'upload.html')

Результат
Независимо от того, как пользователь задает имя файла, сохраняемое имя будет безопасным, без обхода директорий и с низкой вероятностью дублирования.


5. Быстрая справка

from django.utils.text import get_valid_filename

# 1. Основное очищение
safe = get_valid_filename("My: New/Project? 2024*")  # → "My_New_Project_2024"

# 2. Используйте в именах файлов
path = f"media/{safe}.jpg"

# 3. Объедините с UUID для обеспечения уникальности
import uuid
unique_name = f"{uuid.uuid4().hex}_{safe}.jpg"

6. Ключевые моменты

  • get_valid_filename защищает файловую систему от опасных имен всего одним строчкой кода.
  • Используйте его каждый раз, когда преобразуете ввод пользователя или произвольную строку в имя файла.
  • Код аккуратный, кроссплатформенный и безопасный.

Совет: Если вы хотите оставить пробелы или сохранить юникод, вы можете объединить его с slugify или создать пользовательский хелпер, но в большинстве случаев get_valid_filename — лучший вариант.