summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@proxience.com>2015-01-26 11:52:36 +0100
committerÉtienne Loks <etienne.loks@proxience.com>2015-01-26 11:52:36 +0100
commitf468cb6bc7bde671b78c076daaf73a92a8f33a69 (patch)
treed3911ac791217dc5a0ff556afce9743067d1cd1e
parentfea70ced145dcfd326c8846bffa0004009c8daa4 (diff)
downloadIshtar-f468cb6bc7bde671b78c076daaf73a92a8f33a69.tar.bz2
Ishtar-f468cb6bc7bde671b78c076daaf73a92a8f33a69.zip
GeneralType keys: add importer field for specific key association - better management of keys
* new importer field definition and creation * manage manual association of keys * manage overload of keys * manage automatic deletion of keys * change ImportFormater for new management of keys
-rw-r--r--ishtar_common/data_importer.py36
-rw-r--r--ishtar_common/migrations/0019_auto__add_field_itemkey_importer.py249
-rw-r--r--ishtar_common/models.py50
-rw-r--r--ishtar_common/tests.py47
4 files changed, 370 insertions, 12 deletions
diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py
index 3009ba17d..6848c3130 100644
--- a/ishtar_common/data_importer.py
+++ b/ishtar_common/data_importer.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2013-2014 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2013-2015 É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
@@ -185,6 +185,7 @@ class StrChoiceFormater(Formater):
self.equiv_dict = copy.deepcopy(equiv_dict)
self.cli = cli
self.model = model
+ self.create = False
self.missings = set()
for key, value in self.choices:
value = unicode(value)
@@ -206,8 +207,14 @@ class StrChoiceFormater(Formater):
u"Which one is relevant?\n"))
for idx, choice in enumerate(self.choices):
msgstr += u"%d. %s\n" % (idx+1, choice[1])
- msgstr += unicode(_(u"%d. None of the above")) % (idx+2) + u"\n"
+ idx += 2
+ if self.create:
+ msgstr += unicode(_(u"%d. None of the above - create new")) % idx \
+ + u"\n"
+ idx += 1
+ msgstr += unicode(_(u"%d. None of the above - skip")) % idx + u"\n"
for value in values:
+ base_value = copy(value)
value = self.prepare(value)
if value in self.equiv_dict:
continue
@@ -215,7 +222,7 @@ class StrChoiceFormater(Formater):
self.missings.add(value)
continue
res = None
- while res not in range(1, len(self.choices)+2):
+ while res not in range(1, idx+1):
sys.stdout.write(msgstr % value)
res = raw_input(">>> ")
try:
@@ -228,9 +235,18 @@ class StrChoiceFormater(Formater):
if self.model and v:
v = self.model.objects.get(pk=v)
self.equiv_dict[value] = v
+ self.add_key(v, value)
+ elif self.create and res == len(self.choices):
+ self.equiv_dict[value] = self.new(base_value)
else:
self.equiv_dict[value] = None
+ def new(self, value):
+ return
+
+ def add_key(self, obj, value):
+ return
+
def format(self, value):
value = self.prepare(value)
if not self.strict:
@@ -239,7 +255,9 @@ class StrChoiceFormater(Formater):
return self.equiv_dict[value]
class TypeFormater(StrChoiceFormater):
- def __init__(self, model, cli=False):
+ def __init__(self, model, cli=False, defaults={}):
+ self.model = model
+ self.defaults = defaults
self.equiv_dict, self.choices = {}, []
for item in model.objects.all():
self.choices.append((item.pk, unicode(item)))
@@ -249,6 +267,16 @@ class TypeFormater(StrChoiceFormater):
def prepare(self, value):
return slugify(unicode(value).strip())
+ def add_key(self, obj, value):
+ obj.add_key(slugify(value), force=True)
+
+ def new(self, value):
+ values = copy(self.defaults)
+ values['label'] = value
+ values['txt_idx'] = slugify(value)
+ self.model.objects.create(**values)
+ return
+
class DateFormater(Formater):
def __init__(self, date_format="%d/%m/%Y"):
self.date_format = date_format
diff --git a/ishtar_common/migrations/0019_auto__add_field_itemkey_importer.py b/ishtar_common/migrations/0019_auto__add_field_itemkey_importer.py
new file mode 100644
index 000000000..9206279d1
--- /dev/null
+++ b/ishtar_common/migrations/0019_auto__add_field_itemkey_importer.py
@@ -0,0 +1,249 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding field 'ItemKey.importer'
+ db.add_column('ishtar_common_itemkey', 'importer',
+ self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Import'], null=True, blank=True),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'ItemKey.importer'
+ db.delete_column('ishtar_common_itemkey', 'importer_id')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'ishtar_common.arrondissement': {
+ 'Meta': {'object_name': 'Arrondissement'},
+ 'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ },
+ 'ishtar_common.author': {
+ 'Meta': {'object_name': 'Author'},
+ 'author_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.AuthorType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': "orm['ishtar_common.Person']"})
+ },
+ 'ishtar_common.authortype': {
+ 'Meta': {'object_name': 'AuthorType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.canton': {
+ 'Meta': {'object_name': 'Canton'},
+ 'arrondissement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Arrondissement']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ },
+ 'ishtar_common.department': {
+ 'Meta': {'ordering': "['number']", 'object_name': 'Department'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'})
+ },
+ 'ishtar_common.documenttemplate': {
+ 'Meta': {'ordering': "['associated_object_name']", 'object_name': 'DocumentTemplate'},
+ 'associated_object_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'template': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
+ },
+ 'ishtar_common.format': {
+ 'Meta': {'object_name': 'Format'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.globalvar': {
+ 'Meta': {'ordering': "['slug']", 'object_name': 'GlobalVar'},
+ 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
+ 'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.historicalorganization': {
+ 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalOrganization'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'history_creator_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'history_modifier_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'history_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
+ 'merge_key': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'organization_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.import': {
+ 'Meta': {'object_name': 'Import'},
+ 'creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'end_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'error_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'imported_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'result_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'seconds_remaining': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.IshtarUser']"})
+ },
+ 'ishtar_common.ishtaruser': {
+ 'Meta': {'object_name': 'IshtarUser', '_ormbases': ['auth.User']},
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ishtaruser'", 'unique': 'True', 'to': "orm['ishtar_common.Person']"}),
+ 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
+ },
+ 'ishtar_common.itemkey': {
+ 'Meta': {'object_name': 'ItemKey'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'importer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Import']", 'null': 'True', 'blank': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'ishtar_common.organization': {
+ 'Meta': {'object_name': 'Organization'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'merge_candidate': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_candidate_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Organization']"}),
+ 'merge_exclusion': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_exclusion_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Organization']"}),
+ 'merge_key': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'organization_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.OrganizationType']"}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.organizationtype': {
+ 'Meta': {'ordering': "('label',)", 'object_name': 'OrganizationType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.person': {
+ 'Meta': {'object_name': 'Person'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'attached_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'members'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['ishtar_common.Organization']"}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'merge_candidate': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_candidate_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Person']"}),
+ 'merge_exclusion': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_exclusion_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Person']"}),
+ 'merge_key': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'person_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.PersonType']", 'symmetrical': 'False'}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'raw_name': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}),
+ 'surname': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.persontype': {
+ 'Meta': {'ordering': "('label',)", 'object_name': 'PersonType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.sourcetype': {
+ 'Meta': {'object_name': 'SourceType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.supporttype': {
+ 'Meta': {'object_name': 'SupportType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.town': {
+ 'Meta': {'ordering': "['numero_insee']", 'object_name': 'Town'},
+ 'canton': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Canton']", 'null': 'True', 'blank': 'True'}),
+ 'center': ('django.contrib.gis.db.models.fields.PointField', [], {'srid': '27572', 'null': 'True', 'blank': 'True'}),
+ 'departement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'numero_insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '6'}),
+ 'surface': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['ishtar_common'] \ No newline at end of file
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 90232159c..75d2ea544 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -35,7 +35,8 @@ from django.core.validators import validate_slug
from django.core.urlresolvers import reverse, NoReverseMatch
from django.db.utils import DatabaseError
from django.db.models import Q, Max, Count
-from django.db.models.signals import post_save
+from django.db.models.signals import post_save, pre_save
+from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _, ugettext
from django.utils.safestring import SafeUnicode, mark_safe
from django.template.defaultfilters import slugify
@@ -351,8 +352,36 @@ class GeneralType(models.Model):
).split('_')).title()
if not self.txt_idx:
self.txt_idx = slugify(self.label)
+
+ # clean old keys
+ pre_label = getattr(self, 'pre_label', None)
+ pre_txt_idx = getattr(self, 'pre_txt_idx', None)
+ content_type = ContentType.objects.get_for_model(self.__class__)
+ if pre_label and self.label != pre_label:
+ ItemKey.objects.filter(object_id=self.pk, key=slugify(pre_label),
+ content_type=content_type).delete()
+ if pre_txt_idx and self.txt_idx != pre_txt_idx:
+ ItemKey.objects.filter(object_id=self.pk, key=pre_txt_idx,
+ content_type=content_type).delete()
+
+ self.generate_key(force=True)
return super(GeneralType, self).save(*args, **kwargs)
+ def add_key(self, key, force=False):
+ content_type = ContentType.objects.get_for_model(self.__class__)
+ if not force and ItemKey.objects.filter(key=key,
+ content_type=content_type).count():
+ return
+ if force:
+ ItemKey.objects.filter(key=key, content_type=content_type).exclude(
+ object_id=self.pk).delete()
+ ItemKey.objects.get_or_create(object_id=self.pk, key=key,
+ content_type=content_type)
+
+ def generate_key(self, force=False):
+ for key in (slugify(self.label), self.txt_idx):
+ self.add_key(key)
+
def get_keys(self):
keys = []
content_type = ContentType.objects.get_for_model(self.__class__)
@@ -365,18 +394,25 @@ class GeneralType(models.Model):
def generate_keys(cls):
content_type = ContentType.objects.get_for_model(cls)
for item in cls.objects.all():
- for key in (slugify(item.label), item.txt_idx):
- if not ItemKey.objects.filter(object_id=item.pk, key=key,
- content_type=content_type).count():
- ik = ItemKey(object_id=item.pk, key=key,
- content_type=content_type)
- ik.save()
+ item.generate_key()
+
+@receiver(pre_save)
+def pre_save_general_type(sender, **kwargs):
+ if not issubclass(sender, GeneralType) or not 'instance' in kwargs \
+ or not kwargs['instance']:
+ return
+ instance = kwargs['instance']
+ instance.pre_label = instance.label
+ instance.pre_txt_idx = instance.txt_idx
+
class ItemKey(models.Model):
key = models.CharField(_(u"Key"), max_length=100)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
+ importer = models.ForeignKey('Import', null=True, blank=True,
+ help_text=_(u"Key specific to an import"))
def __unicode__(self):
return self.key
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py
index 000abc268..b22d27169 100644
--- a/ishtar_common/tests.py
+++ b/ishtar_common/tests.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2014 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2015 É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
@@ -21,6 +21,8 @@ import tempfile
from zipfile import ZipFile, ZIP_DEFLATED
from django.contrib.auth.models import User
+from django.contrib.contenttypes.models import ContentType
+from django.template.defaultfilters import slugify
from django.test import TestCase
from ishtar_common import models, ooo_replace
@@ -91,3 +93,46 @@ class MergeTest(TestCase):
self.person_3.merge(self.person_1)
# manage well empty many to many fields
self.assertTrue(self.person_types[1] in self.person_3.person_types.all())
+
+class ImportKeyTest(TestCase):
+
+ def testKeys(self):
+ content_type = ContentType.objects.get_for_model(models.OrganizationType)
+
+ # creation
+ label = u"Ploufé"
+ ot = models.OrganizationType.objects.create(label=label)
+ self.assertEqual(models.ItemKey.objects.filter(object_id=ot.pk,
+ key=slugify(label),
+ content_type=content_type).count(), 1)
+ label_2 = u"Plif"
+ ot_2 = models.OrganizationType.objects.create(label=label_2)
+ self.assertEqual(models.ItemKey.objects.filter(object_id=ot_2.pk,
+ key=slugify(label_2),
+ content_type=content_type).count(), 1)
+
+ # replace key
+ ot_2.add_key(slugify(label), force=True)
+ # one key point to only one item
+ self.assertEqual(models.ItemKey.objects.filter(key=slugify(label),
+ content_type=content_type).count(), 1)
+ # this key point to the right item
+ self.assertEqual(models.ItemKey.objects.filter(object_id=ot_2.pk,
+ key=slugify(label), content_type=content_type).count(), 1)
+
+ # modification
+ label_3 = "Yop"
+ ot_2.label = label_3
+ ot_2.save()
+ # old label not referenced anymore
+ self.assertEqual(models.ItemKey.objects.filter(object_id=ot_2.pk,
+ key=slugify(label_2), content_type=content_type).count(), 0)
+ # forced key association is always here
+ self.assertEqual(models.ItemKey.objects.filter(object_id=ot_2.pk,
+ key=slugify(label), content_type=content_type).count(), 1)
+ # new key is here
+ self.assertEqual(models.ItemKey.objects.filter(object_id=ot_2.pk,
+ key=slugify(label_3), content_type=content_type).count(), 1)
+
+
+