summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2019-04-30 13:32:17 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2019-06-17 13:21:27 +0200
commit04a1c3d2b7a7df4e2d0218e56b6c467a5d397f53 (patch)
tree17558137f1faafc5a098aa7e667edd9d884c1f3d
parent8831c2193007000baddb700ba652ed476aac7f03 (diff)
downloadIshtar-04a1c3d2b7a7df4e2d0218e56b6c467a5d397f53.tar.bz2
Ishtar-04a1c3d2b7a7df4e2d0218e56b6c467a5d397f53.zip
Label generation: generate labels from a template - template model, slug is mandatory
-rw-r--r--ishtar_common/admin.py1
-rw-r--r--ishtar_common/migrations/0093_auto_20190429_0950.py3
-rw-r--r--ishtar_common/migrations/0094_auto_20190429_1041.py5
-rw-r--r--ishtar_common/models.py72
-rw-r--r--ishtar_common/models_imports.py30
5 files changed, 79 insertions, 32 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py
index 0e9e7a4bd..23167180a 100644
--- a/ishtar_common/admin.py
+++ b/ishtar_common/admin.py
@@ -1368,6 +1368,7 @@ admin_site.register(models.UserProfile, UserProfileAdmin)
class DocumentTemplateAdmin(admin.ModelAdmin):
list_display = ["name", "associated_model", "available", "for_labels"]
list_filter = ["available", "associated_model"]
+ prepopulated_fields = {"slug": ("name",)}
admin_site.register(models.DocumentTemplate, DocumentTemplateAdmin)
diff --git a/ishtar_common/migrations/0093_auto_20190429_0950.py b/ishtar_common/migrations/0093_auto_20190429_0950.py
index d2bc6a395..a68c91dc2 100644
--- a/ishtar_common/migrations/0093_auto_20190429_0950.py
+++ b/ishtar_common/migrations/0093_auto_20190429_0950.py
@@ -4,6 +4,7 @@ from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
+from django.utils.text import slugify
CLASS_NAMES = {
@@ -26,6 +27,8 @@ def migrate_to_model_fk(apps, schema_editor):
klass=doc.associated_object_name,
defaults={"name": name}
)
+ if not doc.slug:
+ doc.slug = slugify(doc.name)
doc.associated_model = importer_models[doc.associated_object_name]
doc.save()
diff --git a/ishtar_common/migrations/0094_auto_20190429_1041.py b/ishtar_common/migrations/0094_auto_20190429_1041.py
index 6b068b2dc..58f3231e8 100644
--- a/ishtar_common/migrations/0094_auto_20190429_1041.py
+++ b/ishtar_common/migrations/0094_auto_20190429_1041.py
@@ -36,4 +36,9 @@ class Migration(migrations.Migration):
name='associated_model',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.ImporterModel'),
),
+ migrations.AlterField(
+ model_name='documenttemplate',
+ name='slug',
+ field=models.SlugField(max_length=100, unique=True, verbose_name='Identifiant texte'),
+ ),
]
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 43267f6df..ecc43fc07 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -83,7 +83,7 @@ from ishtar_common.models_imports import ImporterModel, ImporterType, \
from ishtar_common.templatetags.link_to_window import simple_link_to_window
from ishtar_common.utils import get_cache, disable_for_loaddata, create_slug, \
get_all_field_names, merge_tsvectors, cached_label_changed, \
- generate_relation_graph, max_size_help, task
+ generate_relation_graph, max_size_help, task, SecretaryRenderer
__all__ = [
'ImporterModel', 'ImporterType', 'ImporterDefault', 'ImporterDefaultValues',
@@ -136,6 +136,8 @@ class ValueGetter(object):
if not prefix:
prefix = self._prefix
values = {}
+ if hasattr(self, "qrcode"):
+ values['qrcode_path'] = self.qrcode_path
for field_name in get_all_field_names(self):
if not hasattr(self, field_name) or \
field_name in self.GET_VALUES_EXCLUDE_FIELDS:
@@ -1632,6 +1634,14 @@ class QRCodeItem(models.Model, ImageContainerModel):
class Meta:
abstract = True
+ @property
+ def qrcode_path(self):
+ if not self.qrcode:
+ self.generate_qrcode()
+ if not self.qrcode: # error on qrcode generation
+ return ""
+ return self.qrcode.path
+
def generate_qrcode(self, request=None, secure=True, tmpdir=None):
url = self.get_absolute_url()
site = Site.objects.get_current()
@@ -1863,7 +1873,30 @@ class GeoItem(models.Model):
return self._geojson_serialize('multi_polygon')
-class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):
+class TemplateItem:
+ @classmethod
+ def _label_templates_q(cls):
+ model_name = "{}.{}".format(
+ cls.__module__, cls.__name__).replace(
+ "models_finds", "models").replace(
+ "models_treatments", "models")
+ return DocumentTemplate.objects.filter(
+ associated_model__klass=model_name,
+ for_labels=True,
+ available=True
+ )
+
+ @classmethod
+ def has_label_templates(cls):
+ return cls._label_templates_q().count()
+
+ @classmethod
+ def label_templates(cls):
+ return cls._label_templates_q()
+
+
+class BaseHistorizedItem(TemplateItem, FullSearch, Imported,
+ JsonData, FixAssociated):
"""
Historized item with external ID management.
All historized items are searchable and have a data json field.
@@ -3064,8 +3097,7 @@ class Dashboard(object):
class DocumentTemplate(models.Model):
name = models.CharField(_("Name"), max_length=100)
- slug = models.SlugField(_("Slug"), blank=True, null=True, max_length=100,
- unique=True)
+ slug = models.SlugField(_("Slug"), max_length=100, unique=True)
associated_model = models.ForeignKey(ImporterModel)
template = models.FileField(
_("Template"), upload_to="templates/%Y/", help_text=max_size_help())
@@ -3109,6 +3141,9 @@ class DocumentTemplate(models.Model):
for item in items.distinct().order_by(*cls._meta.ordering).all():
yield (item.pk, _(str(item)))
+ def get_baselink_for_labels(self):
+ return reverse('generate-labels', args=[self.slug])
+
def publish(self, c_object):
tempdir = tempfile.mkdtemp("-ishtardocs")
output_name = tempdir + os.path.sep + \
@@ -3125,6 +3160,35 @@ class DocumentTemplate(models.Model):
output.write(result)
return output_name
+ def publish_labels(self, objects):
+ if not objects:
+ return
+ tempdir = tempfile.mkdtemp("-ishtarlabels")
+ main_output_name = tempdir + os.path.sep + \
+ slugify(self.name.replace(' ', '_').lower()) + u'-' + \
+ datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')
+ suffix = "." + self.template.name.split('.')[-1]
+ len_objects = len(objects)
+ for idx in range(int(len(objects) / self.label_per_page) + 1):
+ values = {"items": []}
+ for subidx in range(self.label_per_page):
+ c_idx = idx * self.label_per_page + subidx
+ if c_idx >= len_objects:
+ break
+ obj = objects[c_idx]
+ values["items"].append(obj.get_values())
+ engine = SecretaryRenderer()
+ try:
+ result = engine.render(self.template, **values)
+ except TemplateSyntaxError as e:
+ raise TemplateSyntaxError(str(e), e.lineno)
+ output_name = main_output_name + "-" + str(idx + 1) + suffix
+ output = open(output_name, 'wb')
+ output.write(result)
+ # output_name = main_output_name + suffix
+ # TODO: merge docs - return the last for now
+ return output_name
+
class NumberManager(models.Manager):
def get_by_natural_key(self, number):
diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py
index e3f5f2492..23057e6f5 100644
--- a/ishtar_common/models_imports.py
+++ b/ishtar_common/models_imports.py
@@ -19,7 +19,6 @@
import csv
import datetime
-from importlib import import_module
import os
import logging
import shutil
@@ -29,7 +28,7 @@ import zipfile
from django.conf import settings
from django.contrib.gis.db import models
-from django.core.exceptions import SuspiciousOperation, ValidationError
+from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.core.validators import validate_comma_separated_integer_list
from django.db.models.base import ModelBase
@@ -42,7 +41,7 @@ from ishtar_common.model_managers import SlugModelManager
from ishtar_common.utils import create_slug, \
get_all_related_m2m_objects_with_model, put_session_message, \
- put_session_var, get_session_var, num2col, max_size_help
+ put_session_var, get_session_var, num2col, max_size_help, import_class
from ishtar_common.data_importer import Importer, ImportFormater, \
IntegerFormater, FloatFormater, UnicodeFormater, DateFormater, \
TypeFormater, YearFormater, StrToBoolean, FileFormater, InseeFormater, \
@@ -51,12 +50,6 @@ from ishtar_common.utils import task
logger = logging.getLogger(__name__)
-IMPORTER_CLASSES = {}
-
-IMPORTER_CLASSES.update({
- 'sra-pdl-files':
- 'archaeological_files.data_importer.FileImporterSraPdL'})
-
def get_model_fields(model):
"""
@@ -70,22 +63,6 @@ def get_model_fields(model):
return fields
-def import_class(full_path_classname):
- """
- Return the model class from the full path
- TODO: add a white list for more security
- """
- mods = full_path_classname.split('.')
- if len(mods) == 1:
- mods = ['ishtar_common', 'models', mods[0]]
- elif 'models' not in mods and 'models_finds' not in mods \
- and 'models_treatments' not in mods:
- raise SuspiciousOperation(
- u"Try to import a non model from a string")
- module = import_module('.'.join(mods[:-1]))
- return getattr(module, mods[-1])
-
-
class ImportModelManager(models.Manager):
def get_by_natural_key(self, klass):
return self.get(klass=klass)
@@ -149,9 +126,6 @@ class ImporterType(models.Model):
return self.name
def get_importer_class(self, import_instance=None):
- if self.slug and self.slug in IMPORTER_CLASSES:
- cls = import_class(IMPORTER_CLASSES[self.slug])
- return cls
OBJECT_CLS = import_class(self.associated_models.klass)
DEFAULTS = dict([(default.keys, default.values)
for default in self.defaults.all()])