diff options
| author | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-08-18 13:44:22 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-08-18 13:44:22 +0200 | 
| commit | a6d2faa3ffaa9f468ab17e121be02ce0d7495b99 (patch) | |
| tree | 838b2a369a6b10261bb8269366ae5666cb62ecaf | |
| parent | 8bbc6ecf7389357455739154ff1101dc2c1c42d5 (diff) | |
| download | Ishtar-a6d2faa3ffaa9f468ab17e121be02ce0d7495b99.tar.bz2 Ishtar-a6d2faa3ffaa9f468ab17e121be02ce0d7495b99.zip | |
Manage operation relation types in context record and find searches (refs #2799)
| -rw-r--r-- | archaeological_context_records/forms.py | 10 | ||||
| -rw-r--r-- | archaeological_context_records/tests.py | 39 | ||||
| -rw-r--r-- | archaeological_context_records/views.py | 1 | ||||
| -rw-r--r-- | archaeological_finds/forms.py | 15 | ||||
| -rw-r--r-- | archaeological_finds/views.py | 3 | ||||
| -rw-r--r-- | archaeological_operations/tests.py | 7 | ||||
| -rw-r--r-- | ishtar_common/views.py | 47 | 
7 files changed, 101 insertions, 21 deletions
| diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py index 7572b0bcb..512d2069b 100644 --- a/archaeological_context_records/forms.py +++ b/archaeological_context_records/forms.py @@ -30,7 +30,7 @@ from django.utils.translation import ugettext_lazy as _  from ishtar_common.models import valid_id  from archaeological_operations.models import Period, Parcel, Operation, \ -    ArchaeologicalSite +    ArchaeologicalSite, RelationType as OpeRelationType  import models  from ishtar_common import widgets @@ -56,6 +56,9 @@ class RecordSelect(TableSelect):              reverse_lazy('autocomplete-archaeologicalsite'),              associated_model=ArchaeologicalSite),          validators=[valid_id(ArchaeologicalSite)]) +    ope_relation_types = forms.MultipleChoiceField( +        label=_(u"Search within operation relations"), choices=[], +        widget=forms.CheckboxSelectMultiple)      datings__period = forms.ChoiceField(label=_(u"Period"), choices=[])      unit = forms.ChoiceField(label=_(u"Unit type"), choices=[])      parcel = ParcelField(label=_(u"Parcel (section/number/public domain)")) @@ -71,6 +74,8 @@ class RecordSelect(TableSelect):          self.fields['unit'].help_text = models.Unit.get_help()          self.fields['relation_types'].choices = models.RelationType.get_types(              empty_first=False) +        self.fields['ope_relation_types'].choices = OpeRelationType.get_types( +            empty_first=False)      def get_input_ids(self):          ids = super(RecordSelect, self).get_input_ids() @@ -81,6 +86,9 @@ class RecordSelect(TableSelect):          ids.pop(ids.index('relation_types'))          for idx, c in enumerate(self.fields['relation_types'].choices):              ids.append('relation_types_{}'.format(idx)) +        ids.pop(ids.index('ope_relation_types')) +        for idx, c in enumerate(self.fields['ope_relation_types'].choices): +            ids.append('ope_relation_types_{}'.format(idx))          return ids diff --git a/archaeological_context_records/tests.py b/archaeological_context_records/tests.py index 614156528..27ba0ab71 100644 --- a/archaeological_context_records/tests.py +++ b/archaeological_context_records/tests.py @@ -30,6 +30,7 @@ from ishtar_common.models import ImporterType, IshtarSiteProfile  from ishtar_common.tests import create_superuser  from archaeological_operations.tests import OperationInitTest, \      ImportOperationTest +from archaeological_operations import models as models_ope  from archaeological_context_records import models  from ishtar_common import forms_common @@ -126,18 +127,18 @@ class ContextRecordTest(ContextRecordInit, TestCase):      def setUp(self):          IshtarSiteProfile.objects.create()          self.username, self.password, self.user = create_superuser() -        self.create_context_record({"label": u"CR 1"}) -        self.create_context_record({"label": u"CR 2"}) +        self.create_context_record(data={"label": u"CR 1"}) +        self.create_context_record(data={"label": u"CR 2"})          cr_1 = self.context_records[0]          cr_2 = self.context_records[1]          sym_rel_type = models.RelationType.objects.filter(              symmetrical=True).all()[0] +        self.cr_rel_type = sym_rel_type          models.RecordRelations.objects.create(              left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type)      def testSearchExport(self): -        "url = reverse()get-contextrecord-full/csv?submited=1&"          c = Client()          response = c.get(reverse('get-contextrecord'))          # no result when no authentification @@ -145,6 +146,38 @@ class ContextRecordTest(ContextRecordInit, TestCase):          c.login(username=self.username, password=self.password)          response = c.get(reverse('get-contextrecord'))          self.assertTrue(json.loads(response.content)['total'] == 2) +        # test search label +        response = c.get(reverse('get-contextrecord'), +                         {'label': 'cr 1'}) +        self.assertEqual(json.loads(response.content)['total'], 1) +        # test search between relations +        response = c.get(reverse('get-contextrecord'), +                         {'label': 'cr 1', +                          'relation_types_0': self.cr_rel_type.pk}) +        self.assertEqual(json.loads(response.content)['total'], 2) +        # test search between operation relations +        first_ope = self.operations[0] +        first_ope.year = 2010 +        first_ope.save() +        cr_1 = self.context_records[0] +        cr_1.operation = first_ope +        cr_1.save() +        other_ope = self.operations[1] +        other_ope.year = 2016 +        other_ope.save() +        cr_2 = self.context_records[1] +        cr_2.operation = other_ope +        cr_2.save() +        rel_ope = models_ope.RelationType.objects.create( +            symmetrical=True, label='Linked', txt_idx='link') +        models_ope.RecordRelations.objects.create( +            left_record=other_ope, +            right_record=first_ope, +            relation_type=rel_ope) +        response = c.get(reverse('get-contextrecord'), +                         {'operation__year': 2010, +                          'ope_relation_types_0': rel_ope.pk}) +        self.assertEqual(json.loads(response.content)['total'], 2)          # export          response = c.get(reverse('get-contextrecord-full',                                   kwargs={'type': 'csv'}), {'submited': '1'}) diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index 1b8585b82..4e3dcf7fe 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -80,6 +80,7 @@ def autocomplete_contextrecord(request):  get_contextrecord = get_item(      models.ContextRecord,      'get_contextrecord', 'contextrecord', +    relation_types_prefix={'ope_relation_types': 'operation__'},      extra_request_keys=contextrecord_extra_keys,)  get_contextrecord_for_ope = get_item(      models.ContextRecord, diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 7b9c68d75..ba6426cae 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -30,7 +30,8 @@ from django.utils.safestring import mark_safe  from django.utils.translation import ugettext_lazy as _  from ishtar_common.models import Person, valid_id, valid_ids -from archaeological_operations.models import Period, ArchaeologicalSite +from archaeological_operations.models import Period, ArchaeologicalSite, \ +    RelationType as OpeRelationType  from archaeological_context_records.models import DatingType, DatingQuality, \      ContextRecord  from archaeological_warehouse.models import Warehouse @@ -210,6 +211,9 @@ class FindSelect(TableSelect):              reverse_lazy('autocomplete-archaeologicalsite'),              associated_model=ArchaeologicalSite),          validators=[valid_id(ArchaeologicalSite)]) +    ope_relation_types = forms.MultipleChoiceField( +        label=_(u"Search within operation relations"), choices=[], +        widget=forms.CheckboxSelectMultiple)      datings__period = forms.ChoiceField(label=_(u"Period"), choices=[])      # TODO search by warehouse      material_types = forms.ChoiceField(label=_(u"Material type"), choices=[]) @@ -256,6 +260,15 @@ class FindSelect(TableSelect):              models.RemarkabilityType.get_types()          self.fields['remarkabilities'].help_text = \              models.RemarkabilityType.get_help() +        self.fields['ope_relation_types'].choices = OpeRelationType.get_types( +            empty_first=False) + +    def get_input_ids(self): +        ids = super(FindSelect, self).get_input_ids() +        ids.pop(ids.index('ope_relation_types')) +        for idx, c in enumerate(self.fields['ope_relation_types'].choices): +            ids.append('ope_relation_types_{}'.format(idx)) +        return ids  class FindFormSelection(forms.Form): diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index dc8b191ad..20f73c321 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -69,6 +69,9 @@ find_extra_keys = {  get_find = get_item(      models.Find, 'get_find', 'find',      reversed_bool_fields=['image__isnull'], +    relation_types_prefix={ +        'ope_relation_types': +        'base_finds__context_record__operation__'},      base_request={'downstream_treatment__isnull': True},      extra_request_keys=find_extra_keys.copy()) diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index a7ca114f0..2bf3a6691 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -467,11 +467,10 @@ class OperationInitTest(object):          return self.towns      def get_default_town(self): -        town = getattr(self, 'towns', None) -        if not town: +        towns = getattr(self, 'towns', None) +        if not towns:              self.create_towns() -            town = self.towns[0] -        return town +        return self.towns[0]      def create_parcel(self, data={}):          default = {'town': self.get_default_town(), diff --git a/ishtar_common/views.py b/ishtar_common/views.py index d89e35bee..f5471583c 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -19,6 +19,7 @@  from tidylib import tidy_document as tidy +from copy import copy  import csv  import cStringIO as StringIO  import datetime @@ -342,7 +343,7 @@ HIERARCHIC_FIELDS = ['periods', 'period', 'unit', 'material_types',  def get_item(model, func_name, default_name, extra_request_keys=[],               base_request={}, bool_fields=[], reversed_bool_fields=[],               dated_fields=[], associated_models=[], relative_session_names={}, -             specific_perms=[], own_table_cols=None): +             specific_perms=[], own_table_cols=None, relation_types_prefix={}):      """      Generic treatment of tables      """ @@ -406,11 +407,19 @@ def get_item(model, func_name, default_name, extra_request_keys=[],          except ValueError:              return HttpResponse('[]', mimetype='text/plain') -        relation_types = set() -        for k in request_items: -            if k.startswith('relation_types_'): -                relation_types.add(request_items[k]) -                continue +        # manage relations types +        my_rtypes_prefix = copy(relation_types_prefix) +        if 'relation_types' not in my_rtypes_prefix: +            my_rtypes_prefix['relation_types'] = '' +        relation_types = {} +        for rtype_key in my_rtypes_prefix: +            relation_types[my_rtypes_prefix[rtype_key]] = set() +            for k in request_items: +                if k.startswith(rtype_key): +                    relation_types[my_rtypes_prefix[rtype_key]].add( +                        request_items[k]) +                    continue +          for k in request_keys:              val = request_items.get(k)              if not val: @@ -509,14 +518,26 @@ def get_item(model, func_name, default_name, extra_request_keys=[],              alt_dct.update(or_req)              query = query | Q(**alt_dct) -        if relation_types: +        for rtype_prefix in relation_types: +            vals = list(relation_types[rtype_prefix]) +            if not vals: +                continue              alt_dct = { -                'right_relations__relation_type__pk__in': list(relation_types)} +                rtype_prefix + 'right_relations__relation_type__pk__in': vals}              for k in dct:                  val = dct[k] -                if k == 'year': -                    k = 'year__exact' -                alt_dct['right_relations__right_record__' + k] = val +                if rtype_prefix: +                    # only get conditions related to the object +                    if rtype_prefix not in k: +                        continue +                    # tricky: reconstruct the key to make sense - remove the +                    # prefix from the key +                    k = k[0:k.index(rtype_prefix)] + k[ +                        k.index(rtype_prefix) + len(rtype_prefix):] +                if k.endswith('year'): +                    k += '__exact' +                alt_dct[rtype_prefix + 'right_relations__right_record__' + k] =\ +                    val              if not dct:                  # fake condition to trick Django (1.4): without it only the                  # alt_dct is managed @@ -529,7 +550,9 @@ def get_item(model, func_name, default_name, extra_request_keys=[],                      val = or_req[j]                      if j == 'year':                          j = 'year__exact' -                    altor_dct['right_relations__right_record__' + j] = val +                    altor_dct[ +                        rtype_prefix + 'right_relations__right_record__' + j] =\ +                        val                  query = query | Q(**altor_dct)          if own: | 
