How to programmatically create django-imagekit based content instances?

314 Views Asked by At

I am attempting to create default thumbnails for a learning app by using django-imagekit. I'm using Python 3.7.4 and django 3.0.4. I want to create a script to pre-load content, but the ProcessedImageField in my instance is empty after I pass it a django ContentFile. How can I add a model instance from the shell and populate a ProcessedImageField?

Here is my models.py:

from imagekit.models import ProcessedImageField
from imagekit.processors.resize import SmartResize


class MediaThumbnail(models.Model):
    """
    An image that is used to visually represent and distinguish media in the
    site. Implemented via django-imagekit: 
    https://django-imagekit.readthedocs.io/en/latest/

    Attributes:
        thumbnail: An image that uses imagekit processor to resize to a
            standard size.
    """
    thumbnail = ProcessedImageField(upload_to='resource_thumbnails',
                                    processors=[SmartResize(185, 100)],
                                    format='JPEG',
                                    options={'quality': 80}
                                    )

Here is an example shell session:

In [1]: from io import BytesIO                                                                                                         

In [2]: from PIL import Image as PILImage                                                                                              

In [3]: path = "eduhwy/media/default_thumbnails/"                                                                                      

In [4]: img = PILImage.open(path + "abc.jpg")                                                                                          

In [5]: img                                                                                                                            
Out[5]: <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=910x607 at 0x7F49073CAC50>

In [6]: rawfile = BytesIO()                                                                                                            

In [7]: img.save(rawfile, format='jpeg')                                                                                               

In [8]: from django.core.files.base import ContentFile                                                                                 

In [9]: django_file = ContentFile(rawfile.getvalue())                                                                                 

In [10]: mt = MediaThumbnail.objects.create(thumbnail=django_file)                                                                     

In [11]: mt                                                                                                                            
Out[11]: <MediaThumbnail: MediaThumbnail object (724)>

In [12]: mt.thumbnail                                                                                                                  
Out[12]: <ProcessedImageFieldFile: None>

As you can see the thumbnail (ProcessedImageField) is empty. When I use the admin to save one using the same image, it is not empty. How can I get the instance to save with the image intact? Thank you.

1

There are 1 best solutions below

0
On

It turns you that you need to save the thumbnail image as a separate step. In the above code, img is empty. If you do img.seek(0), then there is .jpg content. Basically I needed to do the steps below:

        img = PILImage.open(path + image)
        rawfile = BytesIO()
        img.save(rawfile, format='jpeg')
        mt = MediaThumbnail.objects.create()
        mt.thumbnail.save(image, rawfile)
        rawfile.close()