summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2019-09-04 19:04:05 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2019-09-04 19:04:05 +0200
commit6f6485c8ebf46843209d70bcd4dfb5fb78417c29 (patch)
treec0c99bf70f7df262cd5a76b9b17bcd7dfb84a66c
parentda243748fc3ef819f93835329e5af245b26f2de8 (diff)
downloadIshtar-6f6485c8ebf46843209d70bcd4dfb5fb78417c29.tar.bz2
Ishtar-6f6485c8ebf46843209d70bcd4dfb5fb78417c29.zip
Serialization: finds - UUID for finds, base finds and baskets
-rw-r--r--archaeological_context_records/serializers.py2
-rw-r--r--archaeological_finds/migrations/0070_auto_20190904_1807.py53
-rw-r--r--archaeological_finds/migrations/0071_findbasket_uuid.py31
-rw-r--r--archaeological_finds/models_finds.py13
-rw-r--r--archaeological_finds/serializers.py55
-rw-r--r--archaeological_finds/tests.py93
-rw-r--r--ishtar_common/models.py8
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):