【问题标题】:Django QR code generation PIL image saving using S3 not working使用S3保存Django QR码生成PIL图像不起作用
【发布时间】:2017-06-21 21:32:50
【问题描述】:

我正在尝试根据模型生成二维码。我在 Heroku 托管应用程序并使用 AWS S3 作为存储。 S3 的存储与其他模型元素完全兼容,只是用于生成 QR 码的模型有问题。我使用这个链接作为参考: https://gilang.chandrasa.com/blog/generate-qr-code-in-django-model/ 我的模型是:

class BusinessQRCode(models.Model):
    business = models.ForeignKey(Business, null=True)
    location_name = models.CharField(max_length=255)
    qrcode = models.ImageField(upload_to='documents/{}'.format(time.strftime("%Y/%m/%d")), blank=True, null=True)

    def save(self):
        super(BusinessQRCode, self).save()
        self.generate_qrcode()

    def generate_qrcode(self):
        from activation.models import RandomFileName

        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_L,
            box_size=10,
            border=4,
        )
        qr.add_data('Some data')
        qr.make(fit=True)

        filename = 'qrcode-%s.png' % self.id

        img = qr.make_image()

        from django.conf import settings
        img.save(settings.MEDIA_ROOT + filename)

        # reopen = open(settings.MEDIA_ROOT + filename, "rb")
        # django_file = File(reopen)
        self.qrcode.save(filename,img, save=True)

上面的代码给了我这个错误:

TypeError

TypeError: seek() takes exactly 2 arguments (3 given)

我也尝试过使用注释代码,即打开文件而不是尝试保存它,但它不起作用,它只是永远不会停止加载。我的意思是最后这部分代码:

reopen = open(settings.MEDIA_ROOT + filename, "rb")
django_file = File(reopen)
self.qrcode.save(filename,django_file, save=True)

我做错了什么?

【问题讨论】:

  • 添加错误的回溯。将文件保存到 S3 后端时,您应该使用 django File 对象,如上一个示例所示。 img 是什么类型? S3 后端不会直接从您的本地驱动器读取文件。
  • @HåkenLid img 属于 PIL Pillows 图像类型。我将放置堆栈跟踪。
  • ImageField.save 需要一个 django File 对象,所以我猜这就是当你传递 PIL.Image 时它失败的原因。在默认的本地存储中,我认为您可能会通过将路径名作为字符串传递,但 S3 后端更加严格。

标签: python django amazon-s3 django-models django-1.8


【解决方案1】:

我也尝试过使用注释代码,即打开 文件,而不是试图保存它,但它不起作用,它永远不会 停止加载。

我认为最后一种方法应该可行,但是由于您在保存 ImageField 时使用了save=True,这也会触发父模型的save() 方法。所以你最终会陷入无限循环。

更改保存图像字段和模型的顺序。

def save(self):
    # Generate qrcode before calling super.save
    self.generate_qrcode() 
    super(BusinessQRCode, self).save()

def generate_qrcode(self):

    ...

    with open(settings.MEDIA_ROOT + filename, "rb") as reopen:
        django_file = File(reopen)
        self.qrcode.save(filename,django_file, save=False)

【讨论】:

  • 谢谢,这可行:) 我也会提出解决方案。
  • 在大多数情况下,这种无限递归会很快达到 python 的递归限制,您会看到 RuntimeError: maximum recursion depth exceeded. 但是,由于您每次保存时都通过 Internet 将文件发送到 S3,您将必须等待很长时间才能达到递归限制。如果您在生产中遇到这样的错误,您至少会在从亚马逊收到每月账单时注意到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
相关资源
最近更新 更多