7 долбанных часов...
Это было дико, мать твою!Подробности (не ручаюсь за инфу, мейби говнокодеры с форумов пишут вслепую):- Значт так, в какой-то версии Django метод super save стал break-ать метод save модели
- В какой-то еще версии Django запретили создавать папки изменением self.image.name. Но разрешили в upload_to закидывать функцию с неявными (встроенными) аргументами без возможности добавления (!)
- Решил не париться save и post_save - просто создал внутренний метод и вызываю его перед super save.
Це мой идеальный модельный код:def get_path_upload_image(instance, filename):
"""
Переопределение имени и путя фотографии, сокращение названия
В следующий формат: (media)/photos/username/2019-08-20/photo-name_23-59-59.extension
"""
if '/' in filename:
filename = filename.split('/')[-1]
img_header, img_extension = os.path.splitext(filename)
if len(img_header) > 30:
if img_header[-6:] == '_thumb':
img_header = img_header[:30] + '_thumb'
else:
img_header = img_header[:30]
time = timezone.now().strftime('%Y-%m-%d')
img_name = img_header + '_' + time + img_extension
path = os.path.join('photos', '{}', '{}', '{}').format(instance.user.username, time, img_name)
return path
class Photo(models.Model):
""" Фото """
user = models.ForeignKey(User, verbose_name='Пользователь', on_delete=models.CASCADE)
name = models.CharField('Имя', max_length=50)
image = models.ImageField('Фото', upload_to=get_path_upload_image, blank=True, null=True)
thumbnail = models.ImageField('Превью', upload_to=get_path_upload_image, editable=False, blank=True, null=True)
order = models.PositiveSmallIntegerField('Порядковый номер', null=True, blank=True)
is_main = models.BooleanField('Главное', default=False)
created = models.DateTimeField('Дата создания', auto_now_add=True)
slug = models.SlugField('url', max_length=50, unique=True)
def __str__(self):
return self.name
class Meta:
verbose_name = 'Изображение'
verbose_name_plural = 'Изображения'
def save(self, *args, **kwargs):
self.make_thumbnail()
super(Photo, self).save(*args, **kwargs)
def make_thumbnail(self):
image = Image.open(self.image)
image.thumbnail((120, 80), Image.ANTIALIAS) # ваш размер thumbnail
thumb_name, thumb_extension = os.path.splitext(self.image.name)
thumb_filename = thumb_name + '_thumb' + thumb_extension
temp_thumb = BytesIO()
image.save(temp_thumb, 'JPEG')
temp_thumb.seek(0)
self.thumbnail.save(thumb_filename, ContentFile(temp_thumb.read()), save=False)
temp_thumb.close()
Це мой views:ph = Photo(user=profile.user, order=request.POST.get('files_uploaded'))
im = Image.open(photo_upload_form.cleaned_data['image'])
im = im.convert('RGB')
blob = BytesIO()
if im.width > 1920 or im.height > 1080:
output_size = (1920, 1080)
im.thumbnail(output_size)
im.save(blob, 'JPEG', quality=100)
ph_name = 'gallery{}-{}.jpg'.format(gal.id, timezone.now().strftime('%Y-%m-%d-%H-%M-%S'))
ph.name = ph_name
ph.slug = slugify(ph_name)
ph.image.save(ph_name, File(blob), save=False)
ph.save()
Если че - он сжимает полученное изображение до 1920x1080, закидывает его в photo и автоматически генерит thumbnail - да еще и генерируя путь в зависимости от даты и username.