diff options
| -rw-r--r-- | archaeological_context_records/migrations/0040_auto_20190206_1423.py | 35 | ||||
| -rw-r--r-- | archaeological_context_records/models.py | 17 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0060_auto_20190206_1423.py | 35 | ||||
| -rw-r--r-- | archaeological_finds/models_finds.py | 15 | ||||
| -rw-r--r-- | archaeological_operations/migrations/0050_auto_20190206_1423.py | 55 | ||||
| -rw-r--r-- | archaeological_operations/models.py | 36 | ||||
| -rw-r--r-- | ishtar_common/tests.py | 4 | ||||
| -rw-r--r-- | ishtar_common/utils.py | 84 | 
8 files changed, 256 insertions, 25 deletions
| diff --git a/archaeological_context_records/migrations/0040_auto_20190206_1423.py b/archaeological_context_records/migrations/0040_auto_20190206_1423.py new file mode 100644 index 000000000..b3c5a6837 --- /dev/null +++ b/archaeological_context_records/migrations/0040_auto_20190206_1423.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2019-02-06 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('archaeological_context_records', '0039_auto_20190122_1550'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='contextrecord', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='contextrecord', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +        migrations.AddField( +            model_name='historicalcontextrecord', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='historicalcontextrecord', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +    ] diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index 89526076a..4b41fddb7 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -28,7 +28,7 @@ from django.utils.translation import ugettext_lazy as _, pgettext, \  from django.utils.text import slugify  from ishtar_common.utils import cached_label_changed, \ -    m2m_historization_changed, post_save_point +    m2m_historization_changed, post_save_geo  from ishtar_common.models import Document, GeneralType, \      BaseHistorizedItem, HistoricalRecords, OwnPerms, ShortMenuItem, \ @@ -485,8 +485,16 @@ class ContextRecord(BulkUpdatedItem, BaseHistorizedItem,          blank=True, null=True)      point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True)      point = models.PointField(_(u"Point (3D)"), blank=True, null=True, dim=3) +    point_source = models.CharField( +        _(u"Point source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,                                               null=True) +    multi_polygon_source = models.CharField( +        _(u"Multi-polygon source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      documents = models.ManyToManyField(          Document, related_name='context_records', verbose_name=_(u"Documents"),          blank=True) @@ -528,6 +536,11 @@ class ContextRecord(BulkUpdatedItem, BaseHistorizedItem,              return self.town.center          return self.operation.get_town_centroid() +    def get_town_polygons(self): +        if self.town: +            return self.town.limit +        return self.operation.get_town_polygon() +      @classmethod      def cached_label_bulk_update(cls, operation_id=None, parcel_id=None,                                   transaction_id=None): @@ -752,7 +765,7 @@ class ContextRecord(BulkUpdatedItem, BaseHistorizedItem,  def context_record_post_save(sender, **kwargs):      cached_label_changed(sender=sender, **kwargs) -    post_save_point(sender=sender, **kwargs) +    post_save_geo(sender=sender, **kwargs)  post_save.connect(context_record_post_save, sender=ContextRecord) diff --git a/archaeological_finds/migrations/0060_auto_20190206_1423.py b/archaeological_finds/migrations/0060_auto_20190206_1423.py new file mode 100644 index 000000000..6ddfa5145 --- /dev/null +++ b/archaeological_finds/migrations/0060_auto_20190206_1423.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2019-02-06 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('archaeological_finds', '0059_auto_20190204_1134'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='basefind', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='basefind', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +        migrations.AddField( +            model_name='historicalbasefind', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='historicalbasefind', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +    ] diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index da872ab53..3f0ade1df 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -30,7 +30,7 @@ from django.core.exceptions import ObjectDoesNotExist  from django.utils.translation import ugettext_lazy as _, pgettext_lazy\  from ishtar_common.data_importer import post_importer_action, ImporterError -from ishtar_common.utils import cached_label_changed, post_save_point, \ +from ishtar_common.utils import cached_label_changed, post_save_geo, \      m2m_historization_changed  from ishtar_common.alternative_configs import ALTERNATE_CONFIGS @@ -306,9 +306,17 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, OwnPerms):          blank=True, null=True)      point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True)      point = models.PointField(_(u"Point (3D)"), blank=True, null=True, dim=3) +    point_source = models.CharField( +        _(u"Point source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      line = models.LineStringField(_(u"Line"), blank=True, null=True)      multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,                                               null=True) +    multi_polygon_source = models.CharField( +        _(u"Multi-polygon source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      cache_short_id = models.TextField(          _(u"Short ID"), blank=True, null=True, db_index=True,          help_text=_(u"Cached value - do not edit")) @@ -357,6 +365,9 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, OwnPerms):      def get_town_centroid(self):          return self.context_record.get_town_centroid() +    def get_town_polygons(self): +        return self.context_record.get_town_polygons() +      def generate_index(self):          """          Generate index based on operation or context record (based on @@ -592,7 +603,7 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, OwnPerms):  def post_save_basefind(sender, **kwargs):      cached_label_changed(sender, **kwargs) -    post_save_point(sender, **kwargs) +    post_save_geo(sender, **kwargs)  post_save.connect(post_save_basefind, sender=BaseFind) diff --git a/archaeological_operations/migrations/0050_auto_20190206_1423.py b/archaeological_operations/migrations/0050_auto_20190206_1423.py new file mode 100644 index 000000000..a632b6059 --- /dev/null +++ b/archaeological_operations/migrations/0050_auto_20190206_1423.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2019-02-06 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('archaeological_operations', '0049_auto_20190122_1621'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='archaeologicalsite', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='archaeologicalsite', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +        migrations.AddField( +            model_name='historicalarchaeologicalsite', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='historicalarchaeologicalsite', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +        migrations.AddField( +            model_name='historicaloperation', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='historicaloperation', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +        migrations.AddField( +            model_name='operation', +            name='multi_polygon_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Multi-polygon source'), +        ), +        migrations.AddField( +            model_name='operation', +            name='point_source', +            field=models.CharField(blank=True, choices=[(b'T', 'Commune'), (b'P', 'Precise')], max_length=1, null=True, verbose_name='Point source'), +        ), +    ] diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index a8f1d4faf..2335155ed 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -41,7 +41,7 @@ from ishtar_common.models import BaseHistorizedItem, Dashboard, \      document_attached_changed, HistoryModel, SearchAltName, \      SpatialReferenceSystem  from ishtar_common.utils import cached_label_changed, \ -    force_cached_label_changed, mode, m2m_historization_changed, post_save_point +    force_cached_label_changed, mode, m2m_historization_changed, post_save_geo  class RemainType(GeneralType): @@ -277,8 +277,16 @@ class ArchaeologicalSite(BaseHistorizedItem, OwnPerms, ValueGetter,          blank=True, null=True)      point = models.PointField(_(u"Point"), blank=True, null=True, dim=3)      point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True) +    point_source = models.CharField( +        _(u"Point source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,                                               null=True) +    multi_polygon_source = models.CharField( +        _(u"Multi-polygon source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      documents = models.ManyToManyField(          Document, related_name="sites", verbose_name=_(u"Documents"), @@ -392,6 +400,13 @@ class ArchaeologicalSite(BaseHistorizedItem, OwnPerms, ValueGetter,              return None          return q.all()[0].centroid +    def get_town_polygons(self): +        q = self.towns.filter(limit__isnull=False).annotate( +            poly=Union('limit')).all() +        if not q.count(): +            return None +        return q.all()[0].poly +      def _get_base_image_path(self):          return u"{}/{}".format(self.SLUG, self.reference) @@ -447,7 +462,7 @@ class ArchaeologicalSite(BaseHistorizedItem, OwnPerms, ValueGetter,  def site_post_save(sender, **kwargs):      cached_label_changed(sender=sender, **kwargs) -    post_save_point(sender=sender, **kwargs) +    post_save_geo(sender=sender, **kwargs)  post_save.connect(site_post_save, sender=ArchaeologicalSite) @@ -940,8 +955,16 @@ class Operation(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter,          blank=True, null=True)      point = models.PointField(_(u"Point"), blank=True, null=True, dim=3)      point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True) +    point_source = models.CharField( +        _(u"Point source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,                                               null=True) +    multi_polygon_source = models.CharField( +        _(u"Multi-polygon source"), +        choices=(('T', _(u"Town")), ('P', _(u"Precise"))), max_length=1, +        blank=True, null=True)      history = HistoricalRecords(bases=[HistoryModel])      class Meta: @@ -1115,6 +1138,13 @@ class Operation(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter,              return None          return q.all()[0].centroid +    def get_town_polygons(self): +        q = self.towns.filter(limit__isnull=False).annotate( +            poly=Union('limit')).all() +        if not q.count(): +            return None +        return q.all()[0].poly +      def context_record_relations_q(self):          from archaeological_context_records.models \              import RecordRelations as CRRL @@ -1464,7 +1494,7 @@ for attr in Operation.HISTORICAL_M2M:  def operation_post_save(sender, **kwargs):      if not kwargs['instance']:          return -    post_save_point(sender=sender, **kwargs) +    post_save_geo(sender=sender, **kwargs)      operation = kwargs['instance']      operation.skip_history_when_saving = True diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index 8ecf98255..53ad67faa 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -45,7 +45,7 @@ from django.test.runner import DiscoverRunner  from ishtar_common import models  from ishtar_common import views  from ishtar_common.apps import admin_site -from ishtar_common.utils import post_save_point, update_data, move_dict_data, \ +from ishtar_common.utils import post_save_geo, update_data, move_dict_data, \      rename_and_simplify_media_name, try_fix_file @@ -1589,7 +1589,7 @@ class GeomaticTest(TestCase):              x=2, y=3, z=4,              spatial_reference_system=srs)          self.assertIsNone(obj.point_2d) -        post_save_point(None, instance=obj) +        post_save_geo(None, instance=obj)          self.assertIsNotNone(obj.point_2d)          self.assertIsNotNone(obj.point) diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 20957c43e..0f33fd30d 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -469,10 +469,11 @@ def convert_coordinates_to_point(x, y, z=None, srid=4326):      return geom -def post_save_point(sender, **kwargs): +def post_save_geo(sender, **kwargs):      """      Convert raw x, y, z point to real geo field      """ +    from ishtar_common.models import SpatialReferenceSystem      if not kwargs.get('instance'):          return      instance = kwargs.get('instance') @@ -481,21 +482,72 @@ def post_save_point(sender, **kwargs):      from ishtar_common.models import get_current_profile  # not clean but utils      # must be loaded before models      profile = get_current_profile() -    if instance.x and instance.y and \ -            instance.spatial_reference_system and \ -            instance.spatial_reference_system.auth_name == 'EPSG' and \ -            instance.spatial_reference_system.srid != 0: -        point_2d = convert_coordinates_to_point( -            instance.x, instance.y, srid=instance.spatial_reference_system.srid) -        if instance.z: -            point = convert_coordinates_to_point( -                instance.x, instance.y, instance.z, -                srid=instance.spatial_reference_system.srid) -    elif profile.use_town_for_geo: -        point_2d = instance.get_town_centroid() -    if point_2d != instance.point_2d or point != instance.point: -        instance.point = point -        instance.point_2d = point_2d +    modified = False + +    if (point or point_2d) and instance.x is None:  # db source +        if point: +            current_point = point +            instance.z = point.z +        else: +            current_point = point_2d +        instance.x = current_point.x +        instance.y = current_point.y +        try: +            srs = SpatialReferenceSystem.objects.get( +                srid=int(current_point.srid)) +        except SpatialReferenceSystem.DoesNotExist: +            srs = SpatialReferenceSystem.objects.create( +                srid=int(current_point.srid), +                auth_name='EPSG', +                label=u"EPSG-{}".format(current_point.srid), +                txt_idx=u"epsg-{}".format(current_point.srid), +            ) +        instance.spatial_reference_system = srs +        instance.point_source = 'P' +        if not point_2d: +            instance.point_2d = convert_coordinates_to_point( +                instance.point.x, instance.point.y, +                srid=current_point.srid) +    elif not point_2d: +        source = None +        if instance.x and instance.y and \ +                instance.spatial_reference_system and \ +                instance.spatial_reference_system.auth_name == 'EPSG' and \ +                instance.spatial_reference_system.srid != 0:  # form input +            try: +                point_2d = convert_coordinates_to_point( +                    instance.x, instance.y, +                    srid=instance.spatial_reference_system.srid) +            except forms.ValidationError: +                return  # irrelevant data in DB +            if point_2d: +                source = 'P'  # precise +            if instance.z: +                point = convert_coordinates_to_point( +                    instance.x, instance.y, instance.z, +                    srid=instance.spatial_reference_system.srid) +        elif profile.use_town_for_geo:  # +            point_2d = instance.get_town_centroid() +            source = 'T'  # town + +        if point_2d != instance.point_2d or point != instance.point: +            instance.point = point +            instance.point_2d = point_2d +            instance.point_source = source +            modified = True + +    if instance.multi_polygon and not instance.multi_polygon_source: +        # should be a db source +        instance.multi_polygon_source = 'P' +        modified = True +    elif profile.use_town_for_geo and instance.multi_polygon_source != 'P': +        poly = instance.get_town_polygons() +        if poly and poly != instance.multi_polygon: +            instance.multi_polygon_source = 'T'  # town +            instance.multi_polygon = poly +            modified = True + +    if modified:          instance.skip_history_when_saving = True          instance.save()      return | 
