summaryrefslogtreecommitdiff
path: root/ishtar_common/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common/models.py')
-rw-r--r--ishtar_common/models.py273
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',)