diff options
| -rw-r--r-- | ishtar_common/admin.py | 1 | ||||
| -rw-r--r-- | ishtar_common/migrations/0093_auto_20190429_0950.py | 3 | ||||
| -rw-r--r-- | ishtar_common/migrations/0094_auto_20190429_1041.py | 5 | ||||
| -rw-r--r-- | ishtar_common/models.py | 72 | ||||
| -rw-r--r-- | ishtar_common/models_imports.py | 30 | 
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()]) | 
