templatetags: add a qrcode filter for string values (#55189)

This commit is contained in:
Benjamin Dauvergne 2021-06-24 19:24:47 +02:00
parent bc4112b4c5
commit e9c5baba07
5 changed files with 97 additions and 1 deletions

Binary file not shown.

View File

@ -11,6 +11,10 @@ try:
except ImportError:
langdetect = None
import PIL
from pyzbar.pyzbar import ZBarSymbol
from pyzbar.pyzbar import decode as zbar_decode_qrcode
from wcs import fields
from wcs.formdef import FormDef
from wcs.qommon.http_request import HTTPRequest
@ -1217,3 +1221,27 @@ def test_iterate_days_until(pub):
)
assert t.render({'value': 'error1', 'value2': 'error2'}) == ''
def test_qrcode(pub):
with pub.complex_data():
img = Template('{{ url|qrcode }}').render({'url': 'http://example.com/', 'allow_complex': True})
assert pub.has_cached_complex_data(img)
value = pub.get_cached_complex_data(img)
assert value.orig_filename == 'qrcode.png'
assert value.content_type == 'image/png'
with value.get_file_pointer() as fp:
img = PIL.Image.open(fp)
assert img.size == (330, 330)
assert (
zbar_decode_qrcode(img, symbols=[ZBarSymbol.QRCODE])[0].data.decode() == 'http://example.com/'
)
img = Template('{{ url|qrcode:"qrcode2.png" }}').render(
{'url': 'http://example.com/', 'allow_complex': True}
)
value = pub.get_cached_complex_data(img)
assert value.orig_filename == 'qrcode2.png'
img = Template('{{ url|qrcode }}').render({'url': 1, 'allow_complex': True})
assert img == ''

View File

@ -17,6 +17,8 @@ except ImportError:
Image = None
from django.utils.encoding import force_bytes, force_text
from pyzbar.pyzbar import ZBarSymbol
from pyzbar.pyzbar import decode as zbar_decode_qrcode
from quixote import cleanup, get_publisher, get_response
from quixote.http_request import Upload as QuixoteUpload
@ -3823,6 +3825,50 @@ def test_export_to_model_image(pub, template_name):
)
def test_export_to_model_qrcode(pub):
FormDef.wipe()
formdef = FormDef()
formdef.name = 'baz'
formdef.fields = []
formdef.store()
formdef.data_class().wipe()
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
formdata.store()
pub.substitutions.feed(formdata)
item = ExportToModel()
item.convert_to_pdf = False
item.method = 'non-interactive'
template_filename = os.path.join(os.path.dirname(__file__), 'template-with-qrcode.odt')
with open(template_filename, 'rb') as fd:
template = fd.read()
upload = QuixoteUpload('/foo/template.odt', content_type='application/octet-stream')
upload.fp = io.BytesIO()
upload.fp.write(template)
upload.fp.seek(0)
item.model_file = UploadedFile(pub.app_dir, None, upload)
item.attach_to_history = True
item.perform(formdata)
assert formdata.evolution[-1].parts[-1].base_filename == 'template.odt'
with zipfile.ZipFile(formdata.evolution[-1].parts[0].filename, mode='r') as zfile:
# base template use a jpg images and export_to_model does not rename it
# event when content is PNG, but it still works inside LibreOffice
# which ignores the filename extension.
image_filename = [name for name in zfile.namelist() if name.endswith('.jpg')][0]
with zfile.open(image_filename, 'r') as image_fd:
img = Image.open(image_fd)
assert (
zbar_decode_qrcode(img, symbols=[ZBarSymbol.QRCODE])[0].data.decode()
== 'http://example.net/backoffice/management/baz/1/'
)
def test_export_to_model_backoffice_field(pub):
wf = Workflow(name='email with attachments')
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)

View File

@ -43,6 +43,7 @@ deps =
pylint
Quixote>=3.0,<3.2
pre-commit
pyzbar
commands =
py.test -v {env:COVERAGE:} --junitxml=junit-{envname}.xml {posargs:tests/}
pylint: ./pylint.sh wcs/ tests/

View File

@ -16,6 +16,7 @@
import datetime
import hashlib
import io
import math
import random
import string
@ -26,6 +27,12 @@ from decimal import DivisionByZero as DecimalDivisionByZero
from decimal import InvalidOperation as DecimalInvalidOperation
import pyproj
try:
import qrcode
except ImportError:
qrcode = None
from pyproj import Geod
from quixote import get_publisher
@ -42,7 +49,7 @@ from django.utils.encoding import force_bytes, force_text
from django.utils.safestring import mark_safe
from django.utils.timezone import is_naive, make_aware
from wcs.qommon import calendar, evalutils, tokens
from wcs.qommon import calendar, evalutils, tokens, upload_storage
from wcs.qommon.admin.texts import TextsDirectory
register = template.Library()
@ -817,3 +824,17 @@ def strip_metadata(value):
def list_(value):
# turn a generator into a list
return list(unlazy(value))
@register.filter(name='qrcode')
def qrcode_filter(value, name=None):
if not qrcode:
return ''
if not isinstance(value, str):
return ''
img = qrcode.make(value)
buf = io.BytesIO()
img.save(buf)
upload = upload_storage.PicklableUpload(name or 'qrcode.png', 'image/png')
upload.receive([buf.getvalue()])
return upload