Search code examples
pythondjangoqr-code

How to create qr code from url in django? Calling from another function


I wanted to write a function that takes the generated url for each device and converts it to a qr code. this function should be called in add_new_device after url is created. My code is like this, it's not adding device at the moment.

def add_new_device(self, request):

    user = User.objects.get(username=request.data["username"])
    # last num of device to add in device_id
    last_number = len(Device.objects.all())
    device = Device()
    device = self.write_fields_to_object(device, request.data, user)
    device.device_id = self.random_string_generator() + \
        '-' + str(int(last_number) + 1)
    device.save()

    # Creates new station data added for the device
    self.set_station_data(request.data, device)

    if device.VMIscreen == "true":
        # Creates VMI screen automatically for url
        self.auto_create_new_layout(request, device)
    else:
        # Creates epmtpy screen for url
        empty_layout = Layout()
        self.create_url(empty_layout, device)
        self.create_qr(device)
        

    # Create Event object
    self.create_notification(
        user, device, "add", "device", "has added new Device")

    return "ok"

def create_qr(self, device):
    qr_content = device.screen_url

    qr_name = f'qr_{device.device_id}.png'

    qr = make(qr_content)
    qr.save('media/' + qr_name) 

def create_url(self, layout, device):
   
    screen_url = base_screen_url + device.device_id + ".html"
    Device.objects.filter(device_id=device.device_id).update(
        screen_url=screen_url)
    html = self.edit_device_url_html(layout, device)
    s3.put_object(Bucket=device_url_bucket, Key=str(device.device_id) + ".html", Body=html, ACL='public-read',
                  ContentType='text/html', CacheControl='no-cache, no-store, must-revalidate')

Solution

  • Actually, I would not create a QR code for the Devices, at least not proactively.

    We can construct such QR code on demand, in a view where we want to obtain the QR code. Indeed, such view would look like:

    from io import BytesIO
    
    from django.http import HttpResponse
    from qrcode import make
    from qrcode.image.svg import SvgPathImage
    
    
    def qr_code_for_device(request, pk):
        device = get_object_or_404(Device, pk=pk)
        buffer = BytesIO()
        image = make(device.screen_url, image_factory=SvgPathImage)
        image.save(buffer)
        return HttpResponse(buffer.getvalue(), content_type='image/svg+xml')

    when visiting the view thus for a certain device, it will return an SVG image with the QR code for the screen_url of that device.

    If later the screen_url of the device changes, requesting the qr code with a new request will thus render a QR code with the updated screen_url. It will also save a lot of diskspace, since the images generated only exist in memory until the response is send. Finally performance is likely not an issue here, since QR codes are generated quite efficiently, and actually opening and loading the file to send this as a response is probably comparable in terms of performance, but very likely not that much more efficient.