Skip to content

Commit

Permalink
Add util function to generate qr code for url
Browse files Browse the repository at this point in the history
  • Loading branch information
johannaengland committed May 3, 2024
1 parent 35f1a9b commit 727da71
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog.d/2887.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add functionality to create QR codes to a given url
57 changes: 55 additions & 2 deletions python/nav/web/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
# along with NAV. If not, see <http://www.gnu.org/licenses/>.
#
"""Utils for views"""
import base64
import io
import os

from django.http import HttpResponse


from django.views.generic.list import ListView

import qrcode
from PIL import ImageDraw, ImageFont
import qrcode.image.pil


def get_navpath_root():
"""Returns the default navpath root
Expand Down Expand Up @@ -51,6 +56,7 @@ def require_param(parameter):
Will check both GET and POST querydict for the parameter.
"""

# pylint: disable=missing-docstring
def wrap(func):
def wrapper(request, *args, **kwargs):
Expand All @@ -64,3 +70,50 @@ def wrapper(request, *args, **kwargs):
return wrapper

return wrap


def generate_qr_code(url: str, name: str = "") -> qrcode.image.pil.PilImage:
"""
Generate a QR code from a given url, and, if given, adds the name below as a
caption
Returns the generated image as a PilImage object
"""
# Creating QR code
qr = qrcode.QRCode(box_size=10)
qr.add_data(url)
img = qr.make_image()
draw = ImageDraw.Draw(img)

# Adding the name as caption
if name:
img_width, img_height = img.size
font_dir = os.path.dirname(__file__)
if len(name) < 25:
font = ImageFont.truetype(
os.path.join(font_dir, "static/fonts/OS600.woff"), 25
)
elif len(name) < 50:
font = ImageFont.truetype(

Check warning on line 97 in python/nav/web/utils.py

View check run for this annotation

Codecov / codecov/patch

python/nav/web/utils.py#L96-L97

Added lines #L96 - L97 were not covered by tests
os.path.join(font_dir, "static/fonts/OS600.woff"), 15
)
else:
font = ImageFont.truetype(

Check warning on line 101 in python/nav/web/utils.py

View check run for this annotation

Codecov / codecov/patch

python/nav/web/utils.py#L101

Added line #L101 was not covered by tests
os.path.join(font_dir, "static/fonts/OS600.woff"), 10
)
caption_width = font.getlength(name)
draw.text(
((img_width - caption_width) / 2, img_height - 40),
text=name,
font=font,
fill="black",
)

return img


def convert_pil_object_to_bytes_string(pil_image: qrcode.image.pil.PilImage) -> str:
file_object = io.BytesIO()
pil_image.save(file_object, "PNG")
pil_image.close()
return base64.b64encode(file_object.getvalue()).decode('utf-8')
2 changes: 2 additions & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ pyaml
twisted~=23.8.0 # last version that still supports Python 3.7

networkx==2.6.3
# Cannot be removed as long as qrcode is included
Pillow>3.3.2
qrcode>7.4
pyrad==2.1
sphinx==5.3.0
sphinxcontrib-programoutput==0.17
Expand Down
11 changes: 11 additions & 0 deletions tests/unittests/web/generate_qr_code_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import qrcode.image.pil
from nav.web.utils import convert_pil_object_to_bytes_string, generate_qr_code

import qrcode


def test_generate_qr_code_returns_string():
qr_code = generate_qr_code(url="www.example.com", name="buick.lab.uninett.no")
assert isinstance(qr_code, qrcode.image.pil.PilImage)
qr_code_bytes_string = convert_pil_object_to_bytes_string(qr_code)
assert isinstance(qr_code_bytes_string, str)

0 comments on commit 727da71

Please sign in to comment.