Replace qrcode generator with template tag

This commit is contained in:
Paul Konstantin Gerke 2022-08-25 23:56:18 +02:00
parent abcd832591
commit e238563b53
4 changed files with 112 additions and 27 deletions

View File

@ -86,22 +86,6 @@ class Settings(models.Model):
Token.objects.get(user=self.user).delete()
return Token.objects.get_or_create(user=self.user)[0]
def generate_login_qr_code_png(self, page_root: str) -> bytes:
json_data = {
"url": page_root,
"api_key": str(self.api_key()),
}
qr_code_data = r"BABYBUDDY-LOGIN:" + json.dumps(json_data)
qr = qrcode.QRCode(border=1, box_size=5)
qr.add_data(qr_code_data)
qr.make(fit=True)
image = qr.make_image()
bytesio = io.BytesIO()
image.save(bytesio, format="png")
return bytesio.getbuffer()
@property
def dashboard_refresh_rate_milliseconds(self):
"""

View File

@ -1,5 +1,5 @@
{% extends 'babybuddy/page.html' %}
{% load i18n widget_tweaks %}
{% load i18n widget_tweaks babybuddy_tags %}
{% block title %}{% trans "User Settings" %}{% endblock %}
@ -87,7 +87,12 @@
<div class="form-group row">
<label class="col-sm-2 col-form-label">{% trans "Login QR code" %}</label>
<div class="col-sm-10">
<img src="data:image/png;base64,{{ login_qr_code_png }}">
{% url 'babybuddy:root-router' as relative_root_url %}
{% make_absolute_url relative_root_url as absolute_root_url %}
<img src="{% qrcodepng stripwhitespace %}
BABYBUDDY-LOGIN:{"url":"{{ absolute_root_url }}","api_key":"{{ user.settings.api_key }}"}
{% endqrcodepng %}">
</div>
</div>
</fieldset>

View File

@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
import io
import base64
from multiprocessing.sharedctypes import Value
from django import template
from django.apps import apps
from django.utils import timezone
from django.utils.translation import to_locale, get_language
from django.template.defaultfilters import stringfilter
from core.models import Child
@ -55,3 +60,102 @@ def get_child_count():
@register.simple_tag()
def get_current_timezone():
return timezone.get_current_timezone_name()
@register.simple_tag()
def inline_png_qrcode(qr_code_data, border=1, box_size=5):
import qrcode
qr = qrcode.QRCode(border=border, box_size=box_size)
qr.add_data(qr_code_data)
qr.make(fit=True)
image = qr.make_image()
bytesio = io.BytesIO()
image.save(bytesio, format="png")
base64_data = base64.b64encode(bytesio.getbuffer()).decode()
return f"data:image/png;base64,{base64_data}"
@register.simple_tag(takes_context=True)
def make_absolute_url(context, url):
request = context["request"]
abs_url = request.build_absolute_uri(url)
return abs_url
class QrCodeNode(template.Node):
def __init__(self, nodelist, strip, border, box_size) -> None:
super().__init__()
self.__nodelist = nodelist
self.__strip = strip
self.__border = border
self.__box_size = box_size
def render(self, context):
contents = ""
for node in self.__nodelist:
contents += node.render(context)
if self.__strip:
contents = contents.strip()
import qrcode
qr = qrcode.QRCode(border=self.__border, box_size=self.__box_size)
qr.add_data(contents)
qr.make(fit=True)
image = qr.make_image()
bytesio = io.BytesIO()
image.save(bytesio, format="png")
base64_data = base64.b64encode(bytesio.getbuffer()).decode()
return f"data:image/png;base64,{base64_data}"
@register.tag_function
def qrcodepng(parser, token):
contents = token.split_contents()
params = contents[1:]
def get_parameter(name: str, value_type=None):
search_for = name
if value_type is not None:
search_for += "="
for p in params:
if p.startswith(search_for):
if value_type is None:
if p != search_for:
continue
params.remove(p)
return True
else:
str_value = p[len(search_for) :]
print("AHAGAGAG", str_value)
try:
result = value_type(str_value)
except ValueError:
raise template.TemplateSyntaxError(
f"Invalid parameter '{p}' does "
f"not have type '{value_type}'"
)
else:
params.remove(p)
return result
if value_type is None:
return False
return None
strip = get_parameter("stripwhitespace")
border = get_parameter("border", int) or 1
box_size = get_parameter("box_size", int) or 5
if params:
raise template.TemplateSyntaxError(
f"Unkown arguments for qrcode template tag: {', '.join(params)}"
)
nodelist = parser.parse(("endqrcodepng",))
parser.delete_first_token()
return QrCodeNode(nodelist, strip, border, box_size)

View File

@ -164,20 +164,12 @@ class UserSettings(LoginRequiredMixin, View):
def get(self, request):
settings = request.user.settings
page_root = request.build_absolute_uri(reverse("babybuddy:root-router"))
base64_png = base64.b64encode(
settings.generate_login_qr_code_png(page_root)
)
return render(
request,
self.template_name,
{
"form_user": self.form_user_class(instance=request.user),
"form_settings": self.form_settings_class(
instance=settings
),
"login_qr_code_png": base64_png.decode(),
"form_settings": self.form_settings_class(instance=settings),
},
)