Для работы с загрузкой файлов применял стандартное решение с полем:
thumbnail = models.ImageField(
verbose_name='Карточка публикации',
blank=True,
upload_to= ImageDirectorySave('images/thumbnails/'),
validators=[FileExtensionValidator(
allowed_extensions=('png', 'jpg', 'webp', 'jpeg', 'gif'))
]
)
где в последних аргументах использовались параметры для указания места хранения файлов и фильтр для форматов.
Все работало хорошо - файлы сохранялись и были доступны для применения.
Но возникла необходимость адрес картинки сохранять в отдельном поле, т.к. в некоторых случаях не получалось его достать из связной таблицы.
Неудача возникла при попытке загрузить имя в параметр background . Вполне возможно я не правильно делал ссылку на thumbnail.url. В дальней ем проверю свою теорию, а пока решил в поле модели сохранить адрес изображения.
Для сохранения использовал
self.image_url = self.thumbnail.url
в def save(self, *args, **kwargs): перед сохранением формы.
И во тут возникла проблема с файлами с именами на кириллице. Если прочитать thumbnail.url , то кириллица отображается нормально, но в поле image_url кириллица заменяется на непонятные символы и длина значительно увеличивается, что вызывает ошибку и невозможность сохранения данных.
В интернете есть ряд статей, как кириллицу заменить на латиницу в том числе и для имен.
Приводятся решения
#coding: utf-8
from django.db import models
from pytils import translit
# Picture
class Picture(models.Model):
def get_image_path(self, filename):
path = ''.join(["pictures/",translit.slugify(filename)])
return path
name = models.CharField(max_length=200, default='NoName')
detailImage = models.ImageField(upload_to=get_image_path)
Либо создать свою библиотеку перевода
blog/utils.py
from django.template.defaultfilters import slugify as django_slugify
alphabet = {'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh', 'з': 'z', 'и': 'i',
'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't',
'у': 'u', 'ф': 'f', 'х': 'kh', 'ц': 'ts', 'ч': 'ch', 'ш': 'sh', 'щ': 'shch', 'ы': 'i', 'э': 'e', 'ю': 'yu',
'я': 'ya'}
def slugify(s):
return django_slugify(''.join(alphabet.get(w, w) for w in s.lower()))
Но, как не парадоксально, имя нормально переводится в латиницу, но перед расширением пропадает точка и имя файла теряет признак расширения.
Для устранения этой проблемы была доработана функция
def get_image_path(self, filename):
before_one, after = filename.rsplit('.', 1) # Разделяем с конца по .!
before_one = translit.slugify(before_one) # перевел имя в латиницу
before = before_one[:10]
name = '{}.{}'.format(before, after) # объеденил латиницу и расширение через точку
path = ''.join(["galeria/thumbnails/%Y/%m/%d/", name]) # добавил в путь имя
return path
В данную функцию ввел еще один параметр для сокращения имени файла до 10 знаков.
Теперь имя файла в thumbnail.url сохранялось на латинице и было ограничено по длине.
И теперь можно было спокойно выполнить
self.image_url = self.thumbnail.url
Хотя и здесь не обошлось без проблем когда изначально имя файла длинное. Длина поля image_url была лимитирована max_length=250.
По моим расчетом там был большой запас, учитывая, что имя файла 10 символов плюс добавление на уникальность еще 10 символов, плюс расширение и путь к папке.
Но если имя файла было больше 15 символов, учитывая, что оно должно быть обрезано, все равно выдавалась ошибка превышения длины поля 250. Причину ошибки я не смог определить. Если сохранял файл с именем до 15 символов, конечное имя обрезалось и переводилось на латиницу, а на большем возникала ошибка.
Пока решение было принято - увеличить длину поля до 500. Похоже на бред в данном поле фактическое имя занимало около 100 символов.
Категория: Модели / Добавил: zabariap / 26 июля 2025 г. 12:21
Нет комментариев