When attempting to generate QR codes using QR-code 5.3 using Python3.4. I'm confronted with several issues:
At first I used io.StringIO and I got a string argument expected, got 'bytes' error message. So I then changed io.StringIO to io.BytesIO. Then I got another error which was '_io.BytesIO' object has no attribute 'len' so in order to get the length of the object I used buffer.getbuffer().nbytes but now I'm getting a maximum recursion depth exceeded and it's generating 298 QR code images instead of just one. Any ideas what I am doing wrong?
from django.db import models
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.files.uploadedfile import InMemoryUploadedFile
import random
import qrcode
import io
import sys
from PIL import Image
import pdb;
def qrcode_location(instance, filename):
return '%s/qr_codes/%s' % (instance.user.username, filename)
# Create your models here.
class EmployeeProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
qrcode = models.ImageField(upload_to=qrcode_location, null=True, blank=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
def __str__(self):
return self.first_name + ' ' + self.lastname
def save(self):
first_initial = self.first_name[0].upper()
second_initial = self.last_name[0].upper()
id_number = first_initial + second_initial + str(random.randint(1000000, 9999999))
self.generate_qrcode()
if not EmployeeProfile.objects.filter(employee_id=id_number).exists():
self.employee_id = id_number
super(EmployeeProfile, self).save()
def generate_qrcode(self):
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)
img = qr.make_image()
buffer = io.BytesIO()
img.save(buffer)
filename = 'qrcode.png'
filebuffer = InMemoryUploadedFile(buffer, None, filename, 'image/png', buffer.getbuffer().nbytes, None)
self.qrcode.save(filename, filebuffer)
--------------------SOLUTION UPDATE-------------------------------
Since save was calling generate_qrcode, and that was calling self.qrcode.save and the model was calling save causing infinite recursion. So to prevent that you just need to bypass it by providing an additional third argument to the FileField's save method.
Django FileField in model maximum recursion depth exceeded while calling a Python object
# set 3 argument to false(save=False) otherwise infinite recursion will happen
self.qrcode.save(filename, filebuffer, False)
pdb? Also, it's a stab in the dark, but does the recursion go away if you removeself.qrcode.save?super(EmployeeProfile, self).save()?