diff options
| -rw-r--r-- | archaeological_context_records/serializers.py | 2 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0070_auto_20190904_1807.py | 53 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0071_findbasket_uuid.py | 31 | ||||
| -rw-r--r-- | archaeological_finds/models_finds.py | 13 | ||||
| -rw-r--r-- | archaeological_finds/serializers.py | 55 | ||||
| -rw-r--r-- | archaeological_finds/tests.py | 93 | ||||
| -rw-r--r-- | ishtar_common/models.py | 8 | 
7 files changed, 246 insertions, 9 deletions
| diff --git a/archaeological_context_records/serializers.py b/archaeological_context_records/serializers.py index 6035f0182..70e93f10f 100644 --- a/archaeological_context_records/serializers.py +++ b/archaeological_context_records/serializers.py @@ -51,7 +51,7 @@ def cr_serialization(archive=False, return_empty_types=False,      result = generic_get_results(CR_MODEL_LIST, "context_records",                                   result_queryset=result_queryset)      full_archive = archive_serialization( -        result, archive_dir="operations", archive=archive, +        result, archive_dir="context_records", archive=archive,          return_empty_types=return_empty_types, archive_name=archive_name,      )      return full_archive diff --git a/archaeological_finds/migrations/0070_auto_20190904_1807.py b/archaeological_finds/migrations/0070_auto_20190904_1807.py new file mode 100644 index 000000000..0accfe82c --- /dev/null +++ b/archaeological_finds/migrations/0070_auto_20190904_1807.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.18 on 2019-09-04 18:07 +from __future__ import unicode_literals + +import uuid + +from django.db import migrations, models + +from ishtar_common.utils_migrations import set_uuid_helper + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('archaeological_finds', '0069_auto_20190826_1021'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='basefind', +            name='uuid', +            field=models.UUIDField(blank=True, null=True), +        ), +        migrations.AddField( +            model_name='find', +            name='uuid', +            field=models.UUIDField(blank=True, null=True), +        ), +        migrations.AddField( +            model_name='historicalbasefind', +            name='uuid', +            field=models.UUIDField(default=uuid.uuid4), +        ), +        migrations.AddField( +            model_name='historicalfind', +            name='uuid', +            field=models.UUIDField(default=uuid.uuid4), +        ), +        migrations.RunPython(set_uuid_helper('archaeological_finds', +                                             'BaseFind')), +        migrations.RunPython(set_uuid_helper('archaeological_finds', +                                             'Find')), +        migrations.AlterField( +            model_name='basefind', +            name='uuid', +            field=models.UUIDField(default=uuid.uuid4), +        ), +        migrations.AlterField( +            model_name='find', +            name='uuid', +            field=models.UUIDField(default=uuid.uuid4), +        ), +    ] diff --git a/archaeological_finds/migrations/0071_findbasket_uuid.py b/archaeological_finds/migrations/0071_findbasket_uuid.py new file mode 100644 index 000000000..2098dfa02 --- /dev/null +++ b/archaeological_finds/migrations/0071_findbasket_uuid.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.18 on 2019-09-04 18:30 +from __future__ import unicode_literals + +import uuid + +from django.db import migrations, models + +from ishtar_common.utils_migrations import set_uuid_helper + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('archaeological_finds', '0070_auto_20190904_1807'), +    ] + +    operations = [ +        migrations.AddField( +            model_name='findbasket', +            name='uuid', +            field=models.UUIDField(blank=True, null=True), +        ), +        migrations.RunPython(set_uuid_helper('archaeological_finds', +                                             'FindBasket')), +        migrations.AlterField( +            model_name='findbasket', +            name='uuid', +            field=models.UUIDField(default=uuid.uuid4), +        ), +    ] diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index bd1db0700..1d60f612b 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -19,6 +19,7 @@  from collections import OrderedDict  import datetime +import uuid  from django.conf import settings  from django.contrib.gis.db import models @@ -36,7 +37,7 @@ from ishtar_common.utils import cached_label_changed, post_save_geo, \  from ishtar_common.alternative_configs import ALTERNATE_CONFIGS -from ishtar_common.model_managers import ExternalIdManager +from ishtar_common.model_managers import ExternalIdManager, UUIDModelManager  from ishtar_common.models import Document, GeneralType, \      HierarchicalType, BaseHistorizedItem, LightHistorizedItem, \      HistoricalRecords, OwnPerms, Person, Basket, post_save_cache, \ @@ -271,6 +272,7 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, GeoItem, OwnPerms,      EXTERNAL_ID_KEY = 'base_find_external_id'      EXTERNAL_ID_DEPENDENCIES = ['find']      SLUG = 'basefind' +    uuid = models.UUIDField(default=uuid.uuid4)      label = models.TextField(_(u"Free ID"))      external_id = models.TextField(_(u"External ID"), blank=True, null=True)      auto_external_id = models.BooleanField( @@ -315,7 +317,7 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, GeoItem, OwnPerms,          SearchVectorConfig("cache_complete_id"),          SearchVectorConfig("excavation_id"),      ] -    objects = ExternalIdManager() +    objects = UUIDModelManager()      class Meta:          verbose_name = _(u"Base find") @@ -332,7 +334,7 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, GeoItem, OwnPerms,          return self.label      def natural_key(self): -        return (self.external_id, ) +        return (self.uuid, )      def public_representation(self):          dct = super(BaseFind, self).public_representation() @@ -1441,9 +1443,10 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,      ]      CACHED_LABELS = ['cached_label', 'cached_periods',                       'cached_object_types', 'cached_materials'] -    objects = ExternalIdManager() +    objects = UUIDModelManager()      # fields +    uuid = models.UUIDField(default=uuid.uuid4)      base_finds = models.ManyToManyField(BaseFind, verbose_name=_(u"Base find"),                                          related_name='find')      external_id = models.TextField(_(u"External ID"), blank=True, null=True) @@ -1621,7 +1624,7 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,          ordering = ('cached_label',)      def natural_key(self): -        return (self.external_id, ) +        return (self.uuid, )      @property      def short_class_name(self): diff --git a/archaeological_finds/serializers.py b/archaeological_finds/serializers.py new file mode 100644 index 000000000..5fc8d2224 --- /dev/null +++ b/archaeological_finds/serializers.py @@ -0,0 +1,55 @@ +from ishtar_common.serializers import generic_get_results, archive_serialization +from archaeological_finds import models + + +FIND_MODEL_LIST = [ +    models.BaseFind, models.Find +] + +# TODO: associated documents, property, findbasket + + +def find_serialization(archive=False, return_empty_types=False, +                       archive_name=None, operation_queryset=None, +                       site_queryset=None, cr_queryset=None): +    result_queryset = {} +    if operation_queryset: +        operation_ids = operation_queryset.values_list("id", flat=True) +        result_queryset = { +            models.BaseFind.__name__: +                models.BaseFind.objects.filter( +                    context_record__operation_id__in=operation_ids), +            models.Find.__name__: +                models.Find.objects.filter( +                    base_finds__context_record__operation_id__in=operation_ids), +        } +    elif site_queryset: +        sites = site_queryset.values_list("id", flat=True) +        f_q = { +            "base_finds__context_record__operation__archaeological_site_id__in": sites +        } +        result_queryset = { +            models.BaseFind.__name__: +                models.BaseFind.objects.filter( +                    context_record__operation__archaeological_site_id__in=sites +                ), +            models.Find.__name__: +                models.Find.objects.filter(**f_q), +        } +    elif cr_queryset: +        cr_ids = cr_queryset.values_list("id", flat=True) +        result_queryset = { +            models.BaseFind.__name__: +                models.BaseFind.objects.filter( +                    context_record__in=cr_ids), +            models.Find.__name__: +                models.Find.objects.filter( +                    base_finds__context_record__in=cr_ids), +        } +    result = generic_get_results(FIND_MODEL_LIST, "finds", +                                 result_queryset=result_queryset) +    full_archive = archive_serialization( +        result, archive_dir="operations", archive=archive, +        return_empty_types=return_empty_types, archive_name=archive_name, +    ) +    return full_archive diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index 9d2ff8e8b..63090ce04 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -44,17 +44,18 @@ from archaeological_warehouse.models import Warehouse, WarehouseType, \      ContainerType, Container, WarehouseDivision, WarehouseDivisionLink, \      ContainerLocalisation  from archaeological_operations.models import Operation, OperationType -from archaeological_context_records.models import ContextRecord  from ishtar_common import forms_common  from ishtar_common.tests import WizardTest, WizardTestFormData as FormData, \      TestCase, create_user, create_superuser, AutocompleteTestBase, AcItem, \      FIND_FIXTURES, FIND_TOWNS_FIXTURES, WAREHOUSE_FIXTURES, \ -    CONTEXT_RECORD_FIXTURES, CONTEXT_RECORD_TOWNS_FIXTURES +    COMMON_FIXTURES, GenericSerializationTest  from archaeological_operations.tests import ImportTest, create_operation  from archaeological_context_records.tests import ContextRecordInit +from archaeological_finds import serializers +  class FindInit(ContextRecordInit):      test_context_records = False @@ -114,6 +115,94 @@ class FindInit(ContextRecordInit):              self.base_find = [] +class SerializationTest(GenericSerializationTest, FindInit, TestCase): +    fixtures = COMMON_FIXTURES + WAREHOUSE_FIXTURES + +    def setUp(self): +        ope1 = self.create_operation()[0] +        ope2 = self.create_operation()[1] +        cr = self.create_context_record( +            data={"label": u"CR 1", "operation": ope1} +        )[0] +        cr2 = self.create_context_record( +            data={"label": u"CR 2", "operation": ope2} +        )[1] +        self.create_finds(data_base={"context_record": cr})[0] +        self.create_finds(data_base={"context_record": cr2})[1] +        # basket = models.FindBasket.objects.create(label="Hophop") +        # basket.items.add(self.finds[0]) +        # basket.items.add(self.finds[1]) + +    def test_serialization(self): +        res = self.generic_serialization_test(serializers.find_serialization) +        find_json = json.loads( +            res[('finds', 'archaeological_finds__Find')] +        ) +        self.assertEqual(len(find_json), 2) +        bfind_json = json.loads( +            res[('finds', 'archaeological_finds__BaseFind')] +        ) +        self.assertEqual(len(bfind_json), 2) + +        result_queryset = Operation.objects.filter(uuid=self.operations[0].uuid) +        res = self.generic_serialization_test( +            serializers.find_serialization, no_test=True, +            kwargs={"operation_queryset": result_queryset} +        ) +        find_json = json.loads( +            res[('finds', 'archaeological_finds__Find')] +        ) +        self.assertEqual(len(find_json), 1) +        bfind_json = json.loads( +            res[('finds', 'archaeological_finds__BaseFind')] +        ) +        self.assertEqual(len(bfind_json), 1) + +        result_queryset = ContextRecord.objects.filter( +            uuid=self.context_records[0].uuid) +        res = self.generic_serialization_test( +            serializers.find_serialization, no_test=True, +            kwargs={"cr_queryset": result_queryset} +        ) +        find_json = json.loads( +            res[('finds', 'archaeological_finds__Find')] +        ) +        self.assertEqual(len(find_json), 1) +        bfind_json = json.loads( +            res[('finds', 'archaeological_finds__BaseFind')] +        ) +        self.assertEqual(len(bfind_json), 1) + +        """ +    def test_ope_serialization_with_cr_filter(self): +        res = self.generic_serialization_test( +            operation_serialization, no_test=True, +        ) +        ope_json = json.loads( +            res[('operations', 'archaeological_operations__Operation')] +        ) +        self.assertEqual(len(ope_json), 2) + +        result_queryset = models.ContextRecord.objects.filter( +            uuid=self.context_records[0].uuid) +        res = self.generic_serialization_test( +            operation_serialization, no_test=True, +            kwargs={"cr_queryset": result_queryset} +        ) +        ope_json = json.loads( +            res[('operations', 'archaeological_operations__Operation')] +        ) +        self.assertEqual(len(ope_json), 1) +    """ + +    def test_restore(self): +        current_number, zip_filename = self.generic_restore_test_genzip( +            serializers.FIND_MODEL_LIST, +            serializers.find_serialization) +        self.generic_restore_test(zip_filename, current_number, +                                  serializers.FIND_MODEL_LIST) + +  class FindWizardCreationTest(WizardTest, FindInit, TestCase):      fixtures = WAREHOUSE_FIXTURES      url_name = 'find_creation' diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 8ee72e7b3..2898c7934 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -41,6 +41,7 @@ from PIL import Image  from ooopy.OOoPy import OOoPy  from ooopy.Transformer import Transformer as OOTransformer  import ooopy.Transforms as OOTransforms +import uuid  from django import forms  from django.apps import apps @@ -79,7 +80,7 @@ from ishtar_common.alternative_configs import ALTERNATE_CONFIGS, \  from ishtar_common.data_importer import pre_importer_action  from ishtar_common.model_managers import SlugModelManager, ExternalIdManager, \ -    TypeManager +    TypeManager, UUIDModelManager  from ishtar_common.model_merging import merge_model_objects  from ishtar_common.models_imports import ImporterModel, ImporterType, \      ImporterDefault, ImporterDefaultValues, ImporterColumn, \ @@ -4696,6 +4697,7 @@ class Basket(FullSearch, OwnPerms, ValueGetter, TemplateItem):      Subclass must be defined with an "items" ManyToManyField      """      IS_BASKET = True +    uuid = models.UUIDField(default=uuid.uuid4)      label = models.CharField(_("Label"), max_length=1000)      comment = models.TextField(_("Comment"), blank=True, null=True)      slug = models.SlugField(_("Slug"), blank=True, null=True) @@ -4713,6 +4715,7 @@ class Basket(FullSearch, OwnPerms, ValueGetter, TemplateItem):          IshtarUser, verbose_name=_("Shared (read/edit) with"), blank=True,          related_name='shared_write_%(class)ss'      ) +    objects = UUIDModelManager()      TABLE_COLS = ['label', 'user'] @@ -4731,6 +4734,9 @@ class Basket(FullSearch, OwnPerms, ValueGetter, TemplateItem):      def __str__(self):          return self.label +    def natural_key(self): +        return (self.uuid, ) +      @classmethod      def BASE_REQUEST(cls, request):          if not request.user or not getattr(request.user, 'ishtaruser', None): | 
