我正在使用qrcode生成qrcode。购买机票或购买机票时,我想生成qrcode图像并使用PIL进行一些更改。最后将修改后的画布保存到模型的Image字段中。
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)
但这会引发错误:
AttributeError:'Image'对象没有'_committed'属性
如何将生成的PIL图像保存到django中的ImageField?
答案 0 :(得分:3)
您可以使用BytesIO将Pillow文件保存到内存中的Blob。然后创建一个File
对象并将其传递给模型实例ImageField的save
方法。
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)
查看File
对象的django文档。
https://docs.djangoproject.com/en/2.0/ref/files/file/#the-file-object
您必须使用save=False
,因为默认save=True
表示在保存图像后将调用父模型的save
方法。你不想在这里进行递归,因为你通常会陷入无限循环。
答案 1 :(得分:2)
更改您的代码并使用Django File,如下所示:
ancestor 1
opening hksh1
pasting ancestor 1 to hksh1
opening mysh1
pasting ancestor 1 to mysh1
ancestor 2
opening hksh2
pasting ancestor 2 to hksh2
opening mysh2
pasting ancestor 2 to mysh2
您可以将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)
保存在canvas
和media_root
路径上,也可以保存在临时目录中或使用upload_to
对象。