summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/management/commands/regenerate_qrcodes.py73
-rw-r--r--ishtar_common/models.py60
-rw-r--r--ishtar_common/templates/base.html1
3 files changed, 124 insertions, 10 deletions
diff --git a/ishtar_common/management/commands/regenerate_qrcodes.py b/ishtar_common/management/commands/regenerate_qrcodes.py
new file mode 100644
index 000000000..e56573b06
--- /dev/null
+++ b/ishtar_common/management/commands/regenerate_qrcodes.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2019 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import sys
+import tempfile
+import shutil
+
+from django.core.management.base import BaseCommand
+from django.core.exceptions import FieldDoesNotExist
+
+from django.apps import apps
+
+
+APPS = ['ishtar_common', 'archaeological_operations',
+ 'archaeological_context_records', 'archaeological_finds',
+ 'archaeological_warehouse']
+
+
+class Command(BaseCommand):
+ args = ''
+ help = 'Regenerate QR codes'
+
+ def add_arguments(self, parser):
+ parser.add_argument('app_name', nargs='?', default=None,
+ choices=APPS)
+ parser.add_argument('model_name', nargs='?', default=None)
+
+ def handle(self, *args, **options):
+ limit = options['app_name']
+ model_name = options['model_name']
+ if model_name:
+ model_name = model_name.lower()
+ for app in APPS:
+ if limit and app != limit:
+ continue
+ print(u"* app: {}".format(app))
+ for model in apps.get_app_config(app).get_models():
+ if model_name and model.__name__.lower() != model_name:
+ continue
+ if model.__name__.startswith('Historical'):
+ continue
+ try:
+ model._meta.get_field('qrcode')
+ except FieldDoesNotExist:
+ continue
+ msg = u"-> processing {}: ".format(model._meta.verbose_name)
+ ln = model.objects.count()
+ tmpdir = tempfile.mkdtemp("-qrcode")
+ for idx, object in enumerate(model.objects.all()):
+ object.skip_history_when_saving = True
+ object._no_move = True
+ cmsg = u"\r{} {}/{}".format(msg, idx + 1, ln)
+ sys.stdout.write(cmsg)
+ sys.stdout.flush()
+ object.generate_qrcode(secure=False, tmpdir=tmpdir)
+ shutil.rmtree(tmpdir)
+ sys.stdout.write("\n")
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 9dd90de65..5e81e80a0 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -28,6 +28,7 @@ from jinja2 import TemplateSyntaxError
import json
import logging
import os
+import pyqrcode
import re
import shutil
import tempfile
@@ -45,9 +46,11 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.gis.db import models
from django.contrib.postgres.fields import JSONField
from django.contrib.postgres.search import SearchVectorField, SearchVector
+from django.contrib.sites.models import Site
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
+from django.core.files import File
from django.core.serializers import serialize
from django.core.urlresolvers import reverse, NoReverseMatch
from django.core.validators import validate_slug
@@ -1008,7 +1011,15 @@ def get_image_path(instance, filename):
return instance._get_image_path(filename)
-class ImageModel(models.Model):
+class ImageContainerModel(object):
+ def _get_image_path(self, filename):
+ return u"{}/{}".format(self._get_base_image_path(), filename)
+
+ def _get_base_image_path(self):
+ return u"upload"
+
+
+class ImageModel(models.Model, ImageContainerModel):
image = models.ImageField(upload_to=get_image_path, blank=True, null=True,
max_length=255, help_text=max_size_help())
thumbnail = models.ImageField(
@@ -1021,12 +1032,6 @@ class ImageModel(models.Model):
class Meta:
abstract = True
- def _get_image_path(self, filename):
- return u"{}/{}".format(self._get_base_image_path(), filename)
-
- def _get_base_image_path(self):
- return u"upload"
-
def has_changed(self, field):
if not self.pk:
return True
@@ -1566,6 +1571,40 @@ class FixAssociated(object):
setattr(item, subkey, new_value)
+class QRCodeItem(models.Model, ImageContainerModel):
+ qrcode = models.ImageField(upload_to=get_image_path, blank=True, null=True,
+ max_length=255)
+
+ class Meta:
+ abstract = True
+
+ def generate_qrcode(self, request=None, secure=True, tmpdir=None):
+ url = self.get_absolute_url()
+ site = Site.objects.get_current()
+ if request:
+ scheme = self.request.scheme
+ else:
+ if secure:
+ scheme = "https"
+ else:
+ scheme = "http"
+ url = scheme + "://" + site.domain + url
+ qr = pyqrcode.create(url, version=settings.ISHTAR_QRCODE_VERSION)
+ tmpdir_created = False
+ if not tmpdir:
+ tmpdir = tempfile.mkdtemp("-qrcode")
+ tmpdir_created = True
+ filename = tmpdir + os.sep + 'qrcode.png'
+ qr.png(filename, scale=settings.ISHTAR_QRCODE_SCALE)
+ self.qrcode.save(
+ "qrcode.png", File(open(filename, 'rb')))
+ self.skip_history_when_saving = True
+ self._no_move = True
+ self.save()
+ if tmpdir_created:
+ shutil.rmtree(tmpdir)
+
+
class DocumentItem(object):
@property
def images(self):
@@ -1738,6 +1777,7 @@ class BaseHistorizedItem(DocumentItem, FullSearch, Imported, JsonData,
All historized items are searchable and have a data json field.
"""
IS_BASKET = False
+ SHOW_URL = None
EXTERNAL_ID_KEY = ''
EXTERNAL_ID_DEPENDENCIES = []
HISTORICAL_M2M = []
@@ -1906,9 +1946,11 @@ class BaseHistorizedItem(DocumentItem, FullSearch, Imported, JsonData,
return values
def get_show_url(self):
+ show_url = self.SHOW_URL
+ if not show_url:
+ show_url = 'show-' + self.__class__.__name__.lower()
try:
- return reverse('show-' + self.__class__.__name__.lower(),
- args=[self.pk, ''])
+ return reverse(show_url, args=[self.pk, ''])
except NoReverseMatch:
return
diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html
index 8c2a83713..bcf965ab2 100644
--- a/ishtar_common/templates/base.html
+++ b/ishtar_common/templates/base.html
@@ -52,7 +52,6 @@
var complete_list_label = "{% trans 'complete list...' %}";
var added_message = "{% trans " items added." %}";
var select_only_one_msg = "{% trans "Select only one item." %}";
- var session
var YES = "{% trans 'yes' %}";
var NO = "{% trans 'no' %}";
var show_msg = "{% trans "Show" %}";