Issue
I am using qrcode to generate qrcode. When a ticket is bought, or when bought is true, I would like to generate a qrcode image and make some changes using PIL. Finally save the modified canvas into the Image field of the model.
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)
self.qrcode_file = canvas
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)
But this throws an error:
AttributeError: 'Image' object has no attribute '_committed'
How can I save a generated PIL image into an ImageField in django?
Solution
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.
Answered By - Håken Lid
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.