G
G
gh0sty2019-11-02 18:11:14
Django
gh0sty, 2019-11-02 18:11:14

How to create thumbnail pillow image after saving in django model?

The task is to upload an image and create a thumbnail using Pillow.
The procedure is as follows:

  1. I take a custom image
  2. I create a model object Photo
  3. I fill in the data except for the photo itself
  4. Through Pillow I resize and convert the blob to jpg
  5. I call the save method on the Photo model
  6. The save method creates the download path
  7. The save method should create a thumbnail after super save (which doesn't happen)

I tried via post_save - nothing.
Here are the views:
...

if photo_upload_form.is_valid():
    img_name = 'template{}-{}.jpg'.format(template.id, timezone.now().strftime('%Y-%m-%d-%H-%M-%S'))
    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()
    im.save(blob, 'JPEG', quality=100)
    if im.width > 1920 or im.height > 1080:
        output_size = (1920, 1080)
        im.thumbnail(output_size)
        im.save(blob, 'JPEG', quality=100)
    ph_name = 'template{}-{}.jpg'.format(template.id, timezone.now().strftime('%Y-%m-%d-%H-%M-%S'))
    ph.name = ph_name
    ph.slug = slugify(ph_name)
    print('1')
    ph.image.save(ph_name, File(blob), save=False)
    print('2')
    ph.save()
    print('3')

...

Here is the save:
def save(self, *args, **kwargs):
    print('save')
    self.image.name = get_path_upload_image(self.image.name, self.user.username)
    print('path_got')
    super().save(*args, **kwargs)
    print('saved')
    path = self.image.path
    print(path)
    generate_thumb(Photo, path, **kwargs)
    print('generated')

Here is get_path_upload_image and generate_thumb:
def get_path_upload_image(file, nick):
    """
    Переопределение имени и путя фотографии, сокращение названия
    В следующий формат: (media)/photos/username/2019-08-20/photo-name_23-59-59.extension
    """
    time = timezone.now().strftime('%Y-%m-%d')
    end_extension = file.split('.')[-1]
    head = file.split('.')[0]
    if len(head) > 30:
        head = head.replace('.', '')[:30]
    file_name = head + '_' + timezone.now().strftime('%H-%M-%S') + '.' + end_extension
    path = os.path.join('photos', '{}', '{}', '{}').format(nick, time, file_name)
    return path

#@receiver(post_save, sender=Photo) тож не катит
def generate_thumb(sender, path, **kwargs):
    print('gen')
    # Генерация thumbnail
    if path:
        img = Image.open(path)
        thumb_root_path = '/'.join(path.split('/')[:-1])
        thumb_name = path.split('/')[-1].split('.')[0] + '-thumb.'
        thumb_ext = path.split('/')[-1].split('.')[-1]
        thumb_path = thumb_root_path + thumb_name + thumb_ext
        output_size = (120, 80)
        img.thumbnail(output_size)
        img.save(thumb_path)

The terminal outputs:

1
2
save
path_got
saved
...\media\photos\gh0st\2019-11-02\template402-2019-11-02-14-54-0_14-54-02.jpg
gen
...
File "...\ views.py", line 1055, in profile_create_ad_template_image_upload
ph.save()
File "...\models.py", line 331, in save
generate_thumb(Photo, path, **kwargs)
File "...\models.py ", line 344, in generate_thumb
img = Image.open(path)
...
FileNotFoundError: [Errno 2] No such file or directory: '...\\media\\photos\\gh0st\\2019-11-02 \\template402-2019-11-02-14-54-0_14-54-02.jpg'

The dots are from me.
In media - there really is no object with this name, as if super save scores on self.image.name.
Is "\\" normal? Could it be a shielding issue?
I'm suffering for 3 hours, xs what to do. Pamagity)))

Answer the question

In order to leave comments, you need to log in

1 answer(s)
G
gh0sty, 2019-11-03
@gh0sty

7 fucking hours...
It was fucking crazy!

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()

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()

If so, it compresses the resulting image to 1920x1080, throws it into a photo and automatically generates a thumbnail - and even generating a path depending on the date and username.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question