Save a generated PIL image into an ImageField in django
Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn
--
Track title: CC I Beethoven Sonata No 31 in A Flat M
--
Chapters
00:00 Question
01:12 Accepted answer (Score 13)
02:06 Answer 2 (Score 5)
02:59 Thank you
--
Full question
https://stackoverflow.com/questions/4906...
Question links:
[qrcode]: https://github.com/lincolnloop/python-qr...
Accepted answer links:
https://docs.djangoproject.com/en/2.0/re...
Answer 2 links:
[File]: https://docs.djangoproject.com/en/dev/re...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #django #python3x #pythonimaginglibrary
#avk47
    --
Track title: CC I Beethoven Sonata No 31 in A Flat M
--
Chapters
00:00 Question
01:12 Accepted answer (Score 13)
02:06 Answer 2 (Score 5)
02:59 Thank you
--
Full question
https://stackoverflow.com/questions/4906...
Question links:
[qrcode]: https://github.com/lincolnloop/python-qr...
Accepted answer links:
https://docs.djangoproject.com/en/2.0/re...
Answer 2 links:
[File]: https://docs.djangoproject.com/en/dev/re...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #django #python3x #pythonimaginglibrary
#avk47
ACCEPTED ANSWER
Score 13
You can use a BytesIO to save the Pillow file to an in-memory blob. Then create a File object and pass that to your model instance ImageField's save method.
from io import BytesIO
from django.core.files import File
canvas = Image.new('RGB', (total_width, total_height), 'white')
...
blob = BytesIO()
canvas.save(blob, 'JPEG')  
self.qrcode_file.save('ticket-filename.jpg', File(blob), save=False) 
Check out the django documentation for the File object.
https://docs.djangoproject.com/en/stable/ref/files/file/#the-file-object
You have to use save=False, since the default save=True means that the parent model's save method would be called after the image is saved. You don't want recursion here, since you would typically end up in an infinite loop.
ANSWER 2
Score 5
Change your code and use Django File as below:
from django.core.files import File
class Ticket(models.Model):
    booked_at = models.DateTimeField(default=timezone.now)
    qrcode_file = models.ImageField(upload_to='qrcode', blank=True, null=True)
    bought = models.BooleanField(default=False)
    def save(self, *args, **kwargs):
        if self.bought:
            ...
            ...
            qrcode_img = qrcode.make('some data')
            canvas = Image.new('RGB', (total_width, total_height), 'white')
            draw = ImageDraw.Draw(canvas)
            position = (left, top)
            canvas.paste(qrcode_img, position)
            canvas.save('path/of/dest.png', 'PNG')
            destination_file = open('path/of/dest.png', 'rb')
            self.qrcode_file.save('dest.png', File(destination_file), save=False)
            destination_file.close()
            self.booked_at = timezone.now()
            super(Ticket, self).save(*args, **kwargs)
            canvas.close()
            qrcode_img.close()
        else:
            self.booked_at = timezone.now()
            super(Ticket, self).save(*args, **kwargs)
You can save canvas on the media_root and upload_to path, or in temporary directory or use BytesIO object.