diff options
Diffstat (limited to 'ishtar_common/models.py')
| -rw-r--r-- | ishtar_common/models.py | 273 | 
1 files changed, 262 insertions, 11 deletions
| diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 6c153fb9c..f2193eae2 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -21,11 +21,13 @@  Models description  """  from cStringIO import StringIO +import copy  import datetime  from PIL import Image +from importlib import import_module  import os +import re  import tempfile -import copy  from django.conf import settings  from django.core.cache import cache @@ -51,6 +53,8 @@ from simple_history.models import HistoricalRecords as BaseHistoricalRecords  from ishtar_common.ooo_replace import ooo_replace  from ishtar_common.model_merging import merge_model_objects  from ishtar_common.utils import get_cache +from ishtar_common.data_importer import Importer, ImportFormater, IntegerFormater, \ +        FloatFormater, UnicodeFormater, DateFormater, TypeFormater  def post_save_user(sender, **kwargs):      user = kwargs['instance'] @@ -958,16 +962,264 @@ IMPORT_STATE = (("C", _(u"Created")),                  ("IP", _(u"Import in progress")),                  ("F", _(u"Finished"))) -IMPORT_TYPE = ( -    ('archaeological_files.data_importer.FileImporterSraPdL', -     _("Archaeological files - SRA Pays de la Loire")), -    ('custom', _(u"Custom")) -     ) - -class Import(models.Model): +MODELS = [ +          ('archaeological_operations.models.Operation', _(u"Operation")), +          ('archaeological_operations.models.Parcel', _(u"Parcels")), +          ('archaeological_operations.models.OperationSource', +                                                    _(u"Operation source")), +          ] +if 'archaeological_files' in settings.INSTALLED_APPS: +    MODELS = [('archaeological_files.models.File', _(u"Archaeological files")), +             ] + MODELS + +def get_model_fields(model): +    """ +    Return a dict of fields from  model +    To be replace in Django 1.8 with get_fields, get_field +    """ +    fields = {} +    options = model._meta +    for field in sorted(options.concrete_fields + options.many_to_many + +                        options.virtual_fields): +        fields[field.name] = field +    return fields + +class ImporterType(models.Model):      name = models.CharField(_(u"Name"), blank=True, null=True,                              max_length=100) +    description = models.CharField(_(u"Description"), blank=True, null=True, +                                   max_length=500) +    users = models.ManyToManyField('IshtarUser', verbose_name=_(u"Users"), +                                    blank=True, null=True) +    associated_models = models.CharField(_(u"Associated model"), max_length=200, +                                             choices=MODELS) +    is_template = models.BooleanField(_(u"Is template"), default=False) +    class Meta: +        verbose_name = _(u"Importer - Type") +        verbose_name_plural = _(u"Importer - Types") + +    def __unicode__(self): +        return self.name + +    @property +    def importer_class(self): +        name = ''.join(x for x in slugify(self.name).replace('-', ' ').title() +                       if not x.isspace()) +        OBJECT_CLS = import_module(self.associated_models) +        DEFAULTS = dict((default.keys, default.values) +                                        for default in self.defaults.all()) +        LINE_FORMAT = [] +        idx = 0 +        for column in self.columns.order_by('col_number').all(): +            idx += 1 +            while column.order > idx: +                LINE_FORMAT.append(None) +                idx += 1 +            targets = None +            formater_types = None +            nb = column.targets.count() +            if not nb: +                LINE_FORMAT.append(None) +                continue +            for target in column.targets.all(): +                ft = target.formater_type.get_formater_type() +                if not ft: +                    continue +                formater_types.append(ft) +                targets.append(target.target) +            formater_kwargs = {} +            if column.regexp_pre_filter: +                formater_kwargs['regexp'] = re.compile( +                                                column.regexp_pre_filter.regexp) +            formater_kwargs['duplicate_fields'] = [field.field_name +                                        for field in column.duplicate_fields.all()] +            formater = ImportFormater(targets, formater_types, **formater_kwargs) +            LINE_FORMAT.append(formater) +        args = {'OBJECT_CLS':OBJECT_CLS, 'DESC':self.description, +                'DEFAULTS':DEFAULTS, 'LINE_FORMAT':LINE_FORMAT} +        newclass = type(name, (Importer,), args) +        return newclass + +class ImporterDefault(models.Model): +    importer_type = models.ForeignKey(ImporterType, related_name='defaults') +    target = models.CharField(u"Target", max_length=500) +    class Meta: +        verbose_name = _(u"Importer - Default") +        verbose_name_plural = _(u"Importer - Defaults") + +    @property +    def keys(self): +        return default.target.split('__') + +    @property +    def associated_model(self): +        field = None +        OBJECT_CLS = import_module(self.importer_type.associated_models) +        for idx, item in enumerate(self.keys): +            if not idx: +                field = get_model_fields(OBJECT_CLS)[item] +            else: +                raise NotImplemented() +        if hasattr(field, 'rel') and hasattr(field.rel, 'to'): +            return field.rel.to + +    @property +    def values(self): +        values = {} +        for default_value in self.default_values.all(): +            values[default_value.target] = default_value.get_value() +        return values + +class ImporterDefaultValues(models.Model): +    default_target = models.ForeignKey(ImporterDefault, +                                       related_name='default_values') +    target = models.CharField(u"Target", max_length=500) +    value = models.CharField(u"Value", max_length=500) +    class Meta: +        verbose_name = _(u"Importer - Default value") +        verbose_name_plural = _(u"Importer - Default values") + +    def get_value(self): +        model = self.default_target.associated_model +        if not model: +            return self.value +        # if value is an id +        try: +            return model.objects.get(pk=int(self.value)) +        except (ValueError, model.DoesNotExist): +            pass +        # try with txt_idx +        try: +            return model.objects.get(txt_idx=self.value) +        except (ValueError, model.DoesNotExist): +            pass +        return "" + +class ImporterColumn(models.Model): +    importer_type = models.ForeignKey(ImporterType, related_name='columns') +    col_number = models.IntegerField(_(u"Column number"), default=1) +    regexp_pre_filter = models.ForeignKey("Regexp", blank=True, null=True) +    required = models.BooleanField(_(u"Required"), default=False) +    class Meta: +        verbose_name = _(u"Importer - Column") +        verbose_name_plural = _(u"Importer - Columns") + +class ImporterDuplicateField(models.Model): +    column = models.ForeignKey(ImporterColumn, related_name='duplicate_fields') +    field_name = models.CharField(_(u"Field name"), blank=True, null=True, +                                  max_length=200) +    class Meta: +        verbose_name = _(u"Importer - Duplicate field") +        verbose_name_plural = _(u"Importer - Duplicate fields") + +class Regexp(models.Model): +    name = models.CharField(_(u"Name"), max_length=100) +    description = models.CharField(_(u"Description"), blank=True, null=True, +                                   max_length=500) +    regexp = models.CharField(_(u"Regular expression"), max_length=500) +    class Meta: +        verbose_name = _(u"Importer - Regular expression") +        verbose_name_plural = _(u"Importer - Regular expressions") + +IMPORTER_TYPES = [] + +class ImportTarget(models.Model): +    column = models.ForeignKey(ImporterColumn, related_name='targets') +    target = models.CharField(u"Target", max_length=500) +    regexp_filter = models.ForeignKey("Regexp", blank=True, null=True) +    formater_type = models.ForeignKey("FormaterType") +    class Meta: +        verbose_name = _(u"Importer - Target") +        verbose_name_plural = _(u"Importer - Targets") + +TARGET_MODELS = [ +    ('OrganizationType', _(u"Organization type")), +    ('SourceType', _(u"Source type")), +    ('AuthorType', _(u"Author type")), +    ('Format', _(u"Format")), +    ('archaeological_operations.models.OperationType', _(u"OperationType")), +    ('archaeological_operations.models.Period', _(u"Period")), +    ] + +TARGET_MODELS_KEYS = (tm[0] for tm in TARGET_MODELS) + +IMPORTER_TYPES = ( +    ('IntegerFormater', _(u"Integer")), +    ('FloatFormater', _(u"Float")), +    ('UnicodeFormater', _(u"String")), +    ('DateFormater', _(u"Date")), +    ('TypeFormater', _(u"Type")), +) + +IMPORTER_TYPES_DCT = { +    'IntegerFormater':IntegerFormater, +    'FloatFormater':FloatFormater, +    'UnicodeFormater':UnicodeFormater, +    'DateFormater':DateFormater, +    'TypeFormater':TypeFormater, +} + +DATE_FORMATS = ( +    ('%Y', _(u"4 digit year. e.g.: \"2015\"")), +    ('%Y/%m/%d', _(u"4 digit year/month/day. e.g.: \"2015/02/04\"")), +    ('%d/%m/%Y', _(u"Day/month/4 digit year. e.g.: \"04/02/2015\"")), +) + +IMPORTER_TYPES_CHOICES = {'TypeFormater':TARGET_MODELS, +                          'DateFormater':DATE_FORMATS} + +class FormaterType(models.Model): +    formater_type = models.CharField(u"Formater type", max_length=20, +                                     choices=IMPORTER_TYPES) +    options = models.CharField(_(u"Options"), max_length=500, blank=True, +                               null=True) +    many_split = models.CharField(_(u"Split character(s)"), max_length=10, +                                  blank=True, null=True) +    class Meta: +        verbose_name = _(u"Importer - Formater type") +        verbose_name_plural = _(u"Importer - Formater types") +        unique_together = ('formater_type', 'options', 'many_split') + +    def __unicode__(self): +        return u" - ".join([unicode(dict(IMPORTER_TYPES)[self.formater_type]) +                          if self.formater_type in IMPORTER_TYPES_DCT else ''] + +                        [getattr(self, k) for k in ('options', 'many_split') +                                                        if getattr(self, k)]) + +    def get_choices(self): +        if self.format_type in IMPORTER_TYPES_CHOICES: +            return IMPORTER_TYPES_CHOICES[self.format_type] + +    def get_formater_type(self): +        if self.formater_type not in IMPORTER_TYPES_DCT.keys(): +            return +        kwargs = {} +        if self.many_split: +            kwargs['many_split'] = self.many_split +        if self.formater_type == 'TypeFormater': +            if self.options not in TARGET_MODELS_KEYS: +                return +            model = None +            if self.options in dir(): +                model = dir()[self.options] +            else: +                model = import_module(self.options) +            return TypeFormater(model, **kwargs) +        elif self.formater_type == 'IntegerFormater': +            return IntegerFormater() +        elif self.formater_type == 'FloatFormater': +            return FloatFormater() +        elif self.format_type == 'UnicodeFormater': +            try: +                return UnicodeFormater(int(self.options.strip())) +            except ValueError: +                return +        elif self.format_type == 'DateFormater': +            return DateFormater(self.options) + +class Import(models.Model):      user = models.ForeignKey('IshtarUser') +    importer_type = models.ForeignKey(ImporterType)      imported_file = models.FileField(_(u"Imported file"),                                       upload_to="upload/imports/")      error_file = models.FileField(_(u"Error file"), @@ -976,8 +1228,6 @@ class Import(models.Model):      result_file = models.FileField(_(u"Result file"),                                       upload_to="upload/imports/",                                       blank=True, null=True) -    importer_type = models.CharField(_(u"Importer type"), max_length=200, -                                     choices=IMPORT_TYPE)      state = models.CharField(_(u"State"), max_length=2, choices=IMPORT_STATE)      creation_date = models.DateTimeField(_(u"Creation date"), blank=True,                                           null=True) @@ -990,7 +1240,8 @@ class Import(models.Model):          verbose_name_plural = _(u"Imports")      def __unicode__(self): -        return self.name +        return u"%s - %s" % (unicode(self.importer_type), +                             unicode(self.user))  class Organization(Address, Merge, OwnPerms, ValueGetter):      TABLE_COLS = ('name', 'organization_type',) | 
