diff options
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 |
commit | 07ae3337e7fbefac241eb816f3513b267e2dcd72 (patch) | |
tree | c0c99bf70f7df262cd5a76b9b17bcd7dfb84a66c | |
parent | 35fb017eb816402140317dd9ba78c91f7b68d121 (diff) | |
download | Ishtar-07ae3337e7fbefac241eb816f3513b267e2dcd72.tar.bz2 Ishtar-07ae3337e7fbefac241eb816f3513b267e2dcd72.zip |
Serialization: finds - UUID for finds, base finds and baskets
-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): |