diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-09-19 11:37:42 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-09-19 11:37:42 +0200 |
commit | 5e55409037f385cdbd01710ea11af9cb9584fd9a (patch) | |
tree | 8b0099c79567f3aa32a222a1ecbf6fd17e686b9a | |
parent | ff2b3aac243452b420fce43f0dbce439ac415d81 (diff) | |
download | Ishtar-5e55409037f385cdbd01710ea11af9cb9584fd9a.tar.bz2 Ishtar-5e55409037f385cdbd01710ea11af9cb9584fd9a.zip |
Importers: fix user target key management (refs #3725)
-rw-r--r-- | archaeological_operations/tests.py | 54 | ||||
-rw-r--r-- | archaeological_operations/tests/MCC-operations-example.csv | 2 | ||||
-rw-r--r-- | ishtar_common/data_importer.py | 10 | ||||
-rw-r--r-- | ishtar_common/migrations/0011_auto_20170918_1913.py | 50 | ||||
-rw-r--r-- | ishtar_common/models.py | 42 | ||||
-rw-r--r-- | ishtar_common/models_imports.py | 9 |
6 files changed, 133 insertions, 34 deletions
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index 0d17acb8b..60078b7e2 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -25,6 +25,7 @@ import zipfile from django.conf import settings from django.core.files.uploadedfile import SimpleUploadedFile from django.core.urlresolvers import reverse +from django.db.models import Q from django.test.client import Client from django.contrib.auth.models import User @@ -125,6 +126,11 @@ class ImportTest(object): def init_ope_targetkey(self, imp): # doing manually connections + q = Q(importer=imp) | Q(user=imp.user) + if imp.associated_group: + q |= Q(group=imp.associated_group) + for ik in ItemKey.objects.filter(q).all(): + ik.delete() # target for this import target = TargetKey.objects.filter( @@ -136,39 +142,56 @@ class ImportTest(object): target.save() # target for all users - target2 = TargetKey.objects.get(key='gallo-romain') + tgs = list(TargetKey.objects.filter(key='gallo-romain').all()) + for tg in tgs[1:]: + tg.delete() + target2 = tgs[0] gallo = models.Period.objects.get(txt_idx='gallo-roman') target2.value = gallo.pk target2.is_set = True target2.associated_import = None + target2.associated_group = None + target2.associated_user = None target2.save() # target for this user - target3 = TargetKey.objects.get(key='age-du-fer') + tgs = list(TargetKey.objects.filter(key='age-du-fer').all()) + for tg in tgs[1:]: + tg.delete() + target3 = tgs[0] iron = models.Period.objects.get(txt_idx='iron_age') target3.value = iron.pk target3.is_set = True target3.associated_import = None target3.associated_user = self.ishtar_user + target3.associated_group = None target3.save() # target for another user username, password, user = create_user() another_user = IshtarUser.objects.get(pk=user.pk) - target4 = TargetKey.objects.get(key='neolithique') + tgs = list(TargetKey.objects.filter(key='neolithik').all()) + for tg in tgs[1:]: + tg.delete() + target4 = tgs[0] neo = models.Period.objects.get(txt_idx='neolithic') target4.value = neo.pk target4.is_set = True target4.associated_import = None + target4.associated_group = None target4.associated_user = another_user target4.save() # target for the current group - target5 = TargetKey.objects.get(key='moderne') + tgs = list(TargetKey.objects.filter(key='moderne').all()) + for tg in tgs[1:]: + tg.delete() + target5 = tgs[0] modern = models.Period.objects.get(txt_idx='modern') target5.value = modern.pk target5.is_set = True target5.associated_import = None + target5.associated_user = None target5.associated_group = imp.associated_group target5.save() @@ -271,13 +294,12 @@ class ImportOperationTest(ImportTest, TestCase): self.assertEqual(last_ope.code_patriarche, '4200') self.assertEqual(last_ope.operation_type.txt_idx, 'prog_excavation') - # self.assertEqual(last_ope.periods.count(), 3) - self.assertEqual(last_ope.periods.count(), 4) + self.assertEqual(last_ope.periods.count(), 3) periods = [period.txt_idx for period in last_ope.periods.all()] self.assertIn('iron_age', periods) self.assertIn('gallo-roman', periods) # target key set for another user - # self.assertNotIn('neolithic', periods) + self.assertNotIn('neolithic', periods) # a second importation will be not possible: no two same patriarche # code @@ -298,12 +320,20 @@ class ImportOperationTest(ImportTest, TestCase): importer, form = self.init_ope_import() other_imp = form.save(self.ishtar_user) - # associate with another import - for ik in ItemKey.objects.filter(importer=impt).all(): - ik.importer = other_imp - ik.save() - for tg in TargetKey.objects.filter(associated_import=impt).all(): + # re-associate with another import + q = Q(importer=impt) | Q(user=impt.user) + if impt.associated_group: + q |= Q(group=impt.associated_group) + for ik in ItemKey.objects.filter(q).all(): + ik.delete() + + q = Q(associated_import=impt) | Q(associated_user=impt.user) + if impt.associated_group: + q |= Q(associated_group=impt.associated_group) + for tg in TargetKey.objects.filter(q).all(): + tg.associated_user = None + tg.associated_group = None tg.associated_import = other_imp tg.save() diff --git a/archaeological_operations/tests/MCC-operations-example.csv b/archaeological_operations/tests/MCC-operations-example.csv index 16db46451..bb8fc3084 100644 --- a/archaeological_operations/tests/MCC-operations-example.csv +++ b/archaeological_operations/tests/MCC-operations-example.csv @@ -1,3 +1,3 @@ code OA,region,type operation,intitule operation,operateur,responsable operation,date debut terrain,date fin terrain,chronologie generale,identifiant document georeferencement,notice scientifique 4201,Bourgogne,Fouille programmée,Oppìdum de Paris 2,L'opérateur,,2000/01/31,2002/12/31,Age du Fer,, -4200,Bourgogne,Fouille programmée,Oppìdum de Paris,L'opérateur,Jean Sui-Resp'on Sablé,2000/01/22,2002/12/31,Age du Fer & Gallo-Romain & Néolithique & Moderne,, +4200,Bourgogne,Fouille programmée,Oppìdum de Paris,L'opérateur,Jean Sui-Resp'on Sablé,2000/01/22,2002/12/31,Age du Fer & Gallo-Romain & Néolithik & Moderne,, diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py index 00aa34f4c..b88fbff2f 100644 --- a/ishtar_common/data_importer.py +++ b/ishtar_common/data_importer.py @@ -431,7 +431,7 @@ class StrChoiceFormater(Formater, ChoiceChecker): if self.model and v: v = self.model.objects.get(pk=v) self.equiv_dict[value] = v - self.add_key(v, value) + self.add_key(v, value, import_instance) self.new_keys[value] = v elif self.create and res == len(self.choices): self.equiv_dict[value] = self.new(base_value) @@ -479,7 +479,7 @@ class StrChoiceFormater(Formater, ChoiceChecker): def new(self, value): return - def add_key(self, obj, value): + def add_key(self, obj, value, importer=None): return def format(self, value): @@ -509,14 +509,14 @@ class TypeFormater(StrChoiceFormater): if self.import_instance: for item in model.objects.all(): self.choices.append((item.pk, unicode(item))) - for key in item.get_keys(importer_id=import_instance.pk): + for key in item.get_keys(importer=import_instance): self.equiv_dict[key] = item def prepare(self, value): return slugify(unicode(value).strip()) - def add_key(self, obj, value): - obj.add_key(slugify(value), force=True) + def add_key(self, obj, value, importer=None): + obj.add_key(slugify(value), force=True, importer=importer) def new(self, value): values = copy.copy(self.defaults) diff --git a/ishtar_common/migrations/0011_auto_20170918_1913.py b/ishtar_common/migrations/0011_auto_20170918_1913.py new file mode 100644 index 000000000..30ae07fd8 --- /dev/null +++ b/ishtar_common/migrations/0011_auto_20170918_1913.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-09-18 19:13 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0010_auto_20170829_1716'), + ] + + operations = [ + migrations.AlterModelOptions( + name='targetkey', + options={'ordering': ('target', 'key'), 'verbose_name': 'Importer - Target key', 'verbose_name_plural': 'Importer - Targets keys'}, + ), + migrations.AddField( + model_name='itemkey', + name='group', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.TargetKeyGroup'), + ), + migrations.AddField( + model_name='itemkey', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.IshtarUser'), + ), + migrations.AlterField( + model_name='import', + name='associated_group', + field=models.ForeignKey(blank=True, help_text='If a group is selected, target key saved in this group will be used.', null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.TargetKeyGroup'), + ), + migrations.AlterField( + model_name='import', + name='conservative_import', + field=models.BooleanField(default=False, help_text='If set to true, do not overload existing values.', verbose_name='Conservative import'), + ), + migrations.AlterField( + model_name='import', + name='name', + field=models.CharField(max_length=500, null=True, verbose_name='Name'), + ), + migrations.AlterField( + model_name='import', + name='skip_lines', + field=models.IntegerField(default=1, help_text='Number of header lines in your file (can be 0).', verbose_name='Skip lines'), + ), + ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index a4fe5af7f..53d5c85ac 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -717,33 +717,43 @@ class GeneralType(Cached, models.Model): self.generate_key(force=True) return obj - def add_key(self, key, force=False, importer=None): + def add_key(self, key, force=False, importer=None, group=None, + user=None): content_type = ContentType.objects.get_for_model(self.__class__) if not importer and not force and ItemKey.objects.filter( key=key, content_type=content_type).count(): return + filtr = {'key': key, 'content_type': content_type} + if group: + filtr['group'] = group + elif user: + filtr['user'] = user + else: + filtr['importer'] = importer if force: - ItemKey.objects.filter(key=key, content_type=content_type, - importer=importer)\ - .exclude(object_id=self.pk).delete() - ItemKey.objects.get_or_create( - object_id=self.pk, key=key, content_type=content_type, - importer=importer - ) + ItemKey.objects.filter(**filtr).exclude(object_id=self.pk).delete() + filtr['object_id'] = self.pk + ItemKey.objects.get_or_create(**filtr) def generate_key(self, force=False): for key in (slugify(self.label), self.txt_idx): self.add_key(key) - def get_keys(self, importer_id=None): + def get_keys(self, importer): keys = [self.txt_idx] content_type = ContentType.objects.get_for_model(self.__class__) - query = Q(content_type=content_type, object_id=self.pk, - importer__isnull=True) - if importer_id: - query |= Q(content_type=content_type, object_id=self.pk, - importer__pk=importer_id) - q = ItemKey.objects.filter(query) + base_q = Q(content_type=content_type, object_id=self.pk) + subquery = Q(importer__isnull=True, user__isnull=True, + group__isnull=True) + subquery |= Q(user__isnull=True, group__isnull=True, + importer=importer) + if importer.user: + subquery |= Q(user=importer.user, group__isnull=True, + importer=importer) + if importer.associated_group: + subquery |= Q(user__isnull=True, group=importer.associated_group, + importer=importer) + q = ItemKey.objects.filter(base_q & subquery) for ik in q.exclude(key=self.txt_idx).all(): keys.append(ik.key) return keys @@ -763,6 +773,8 @@ class ItemKey(models.Model): importer = models.ForeignKey( Import, null=True, blank=True, help_text=_(u"Specific key to an import")) + user = models.ForeignKey('IshtarUser', blank=True, null=True) + group = models.ForeignKey(TargetKeyGroup, blank=True, null=True) def __unicode__(self): return self.key diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py index ccb0f2c57..d82d0580f 100644 --- a/ishtar_common/models_imports.py +++ b/ishtar_common/models_imports.py @@ -584,7 +584,14 @@ class TargetKey(models.Model): except self.target.associated_model.DoesNotExist: pass if v: - v.add_key(self.key, importer=self.associated_import) + keys = {} + if self.associated_group: + keys['group'] = self.associated_group + if self.associated_user: + keys['user'] = self.associated_user + else: + keys['importer'] = self.associated_import + v.add_key(self.key, **keys) return obj TARGET_MODELS = [ |