From cd1550ecd32518a8d198ec153ac15c1be1d1a264 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 11:18:31 -0500 Subject: [PATCH 01/10] new RelatedLink format choices, update helptext ref #958 --- apps/iiif/choices.py | 6 ++- ..._alter_relatedlink_format_and_data_type.py | 39 +++++++++++++++++++ apps/iiif/manifests/models.py | 8 +++- 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py diff --git a/apps/iiif/choices.py b/apps/iiif/choices.py index 0a10fe196..0d9b60831 100644 --- a/apps/iiif/choices.py +++ b/apps/iiif/choices.py @@ -6,11 +6,13 @@ class Choices(): """ List of Mime type choices. """ MIMETYPES = ( - ('text/html', 'HTML'), + ('text/html', 'HTML or web page'), ('application/json', 'JSON'), ('application/ld+json', 'JSON-LD'), + ('application/pdf', 'PDF'), + ('text/plain', 'Text'), ('application/xml', 'XML'), - ('text/plan', 'Text'), + ('application/octet-stream', 'Other'), ) """ diff --git a/apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py b/apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py new file mode 100644 index 000000000..875e79d25 --- /dev/null +++ b/apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.12 on 2023-12-05 16:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("manifests", "0057_alter_manifest_languages"), + ] + + operations = [ + migrations.AlterField( + model_name="relatedlink", + name="data_type", + field=models.CharField( + default="Dataset", + help_text="Leave as 'Dataset' for structured data describing this document (e.g. a remote manifest) and this link will appear in 'seeAlso'; change to any other value and it will only appear in the 'related' property of the manifest.", + max_length=255, + ), + ), + migrations.AlterField( + model_name="relatedlink", + name="format", + field=models.CharField( + blank=True, + choices=[ + ("text/html", "HTML or web page"), + ("application/json", "JSON"), + ("application/ld+json", "JSON-LD"), + ("application/pdf", "PDF"), + ("text/plain", "Text"), + ("application/xml", "XML"), + ("application/octet-stream", "Other"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index b3eb4c654..426f0f31b 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -341,7 +341,13 @@ class RelatedLink(models.Model): """ Links to related resources """ id = models.UUIDField(primary_key=True, default=uuid4) link = models.CharField(max_length=255) - data_type = models.CharField(max_length=255, default='Dataset') + data_type = models.CharField( + max_length=255, + default='Dataset', + help_text="Leave as 'Dataset' for structured data describing this document (e.g. a " + + "remote manifest) and this link will appear in 'seeAlso'; change to any other value and " + + "it will only appear in the 'related' property of the manifest.", + ) label = GenericRelation(ValueByLanguage) format = models.CharField(max_length=255, choices=Choices.MIMETYPES, blank=True, null=True) profile = models.CharField(max_length=255, blank=True, null=True) From 87f80b42bf0aeb7435c88bca4841aa70e1b86af3 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 11:18:59 -0500 Subject: [PATCH 02/10] Add RelatedLinks inline to Manifest admin --- apps/iiif/manifests/admin.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/iiif/manifests/admin.py b/apps/iiif/manifests/admin.py index 476257392..ff697617e 100644 --- a/apps/iiif/manifests/admin.py +++ b/apps/iiif/manifests/admin.py @@ -6,7 +6,7 @@ from import_export.admin import ImportExportModelAdmin from import_export.widgets import ManyToManyWidget, ForeignKeyWidget from django_summernote.admin import SummernoteModelAdmin -from .models import Manifest, Note, ImageServer +from .models import Manifest, Note, ImageServer, RelatedLink from .forms import ManifestAdminForm from .views import AddToCollectionsView from ..kollections.models import Collection @@ -32,6 +32,17 @@ class Meta: # pylint: disable=too-few-public-methods, missing-class-docstring 'pdf', 'metadata', 'attribution', 'logo', 'logo_url', 'license', 'viewingdirection', 'collection_id' ) + +class RelatedLinksInline(admin.TabularInline): + model = RelatedLink + fields = ( + "link", + "data_type", + "format", + ) + extra = 1 + min_num = 0 + class ManifestAdmin(ImportExportModelAdmin, SummernoteModelAdmin, admin.ModelAdmin): """Django admin configuration for manifests""" resource_class = ManifestResource @@ -42,6 +53,7 @@ class ManifestAdmin(ImportExportModelAdmin, SummernoteModelAdmin, admin.ModelAdm summernote_fields = ('summary',) form = ManifestAdminForm actions = ['add_to_collections_action'] + inlines = [RelatedLinksInline] def add_to_collections_action(self, request, queryset): """Action choose manifests to add to collections""" From 374f4190eb49da999ac71be4aa6c01d853f3cab3 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 11:20:37 -0500 Subject: [PATCH 03/10] Update serialization: separate seeAlso and related (#958) --- apps/iiif/manifests/models.py | 33 ++++++++++++++++++++++++++++-- apps/iiif/manifests/tests/tests.py | 2 +- apps/iiif/serializers/manifest.py | 5 ++--- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index 426f0f31b..614efbf53 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -259,8 +259,37 @@ def related_links(self): :return: List of links related to Manifest :rtype: list """ - links = [link.link for link in self.relatedlink_set.all()] - links.append(self.get_volume_url()) + links = [ + { + "@id": link.link, + "format": link.format, + } if link.format else link.link + for link in self.relatedlink_set.all() + ] + links.append({ + "@id": self.get_volume_url(), + "format": "text/html" + }) + return links + + @property + def see_also_links(self): + """List of links for IIIF v2 'seeAlso' field (structured data). + + :return: List of links to structured data describing Manifest + :rtype: list + """ + links = [] + for link in self.relatedlink_set.all(): + if link.data_type.lower() == "dataset": + links.append( + { + "@id": link.link, + "format": link.format, + } + if link.format + else link.link + ) return links # TODO: Is this needed? It doesn't seem to be called anywhere. diff --git a/apps/iiif/manifests/tests/tests.py b/apps/iiif/manifests/tests/tests.py index e30228bc2..16be42f34 100644 --- a/apps/iiif/manifests/tests/tests.py +++ b/apps/iiif/manifests/tests/tests.py @@ -175,7 +175,7 @@ def test_serialized_related_links(self): [manifest] ) ) - assert 'seeAlso' not in no_links.keys() + assert not no_links['seeAlso'] link = RelatedLink(link='images.org', manifest=manifest) link.save() diff --git a/apps/iiif/serializers/manifest.py b/apps/iiif/serializers/manifest.py index bd55ebd42..cef2da43e 100644 --- a/apps/iiif/serializers/manifest.py +++ b/apps/iiif/serializers/manifest.py @@ -125,10 +125,9 @@ def get_dump_object(self, obj): ) ) } - ] + ], + "seeAlso": obj.see_also_links, } - if obj.relatedlink_set.exists(): - data["seeAlso"] = [related.link for related in obj.relatedlink_set.all()] return data return None From 04c8f9b37e6956ccbb89f1d2921b11b82d7b8425 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 12:26:35 -0500 Subject: [PATCH 04/10] Create RelatedLink objects from "related" column ref #958 --- apps/ingest/services.py | 39 +++++++++++++++++++++++++++------ apps/ingest/tasks.py | 9 ++++++-- apps/ingest/tests/test_local.py | 17 ++++++++++++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/apps/ingest/services.py b/apps/ingest/services.py index 3af4ab6ea..365283dff 100644 --- a/apps/ingest/services.py +++ b/apps/ingest/services.py @@ -19,7 +19,10 @@ def clean_metadata(metadata): :rtype: dict """ metadata = {key.casefold().replace(' ', '_'): value for key, value in metadata.items()} - fields = [f.name for f in Manifest._meta.get_fields()] + fields = [ + *(f.name for f in Manifest._meta.get_fields()), + "related", # used for related external links + ] invalid_keys = [] for key in metadata.keys(): @@ -33,13 +36,31 @@ def clean_metadata(metadata): if key not in fields: invalid_keys.append(key) + # TODO: Update this method to allow all "invalid" keys to populate Manifest.metadata JSONField for invalid_key in invalid_keys: metadata.pop(invalid_key) - - return metadata +def create_related_links(manifest, related_str): + """ + Create RelatedLink objects from supplied related links string and associate each with supplied + Manifest. String should consist of semicolon-separated URLs. + :param manifest: + :type related_str: iiif.manifest.models.Manifest + :param related_str: + :type related_str: str + :rtype: None + """ + for link in related_str.split(";"): + (format, _) = guess_type(link) + RelatedLink.objects.create( + manifest=manifest, + link=link, + format=format or "text/html", # assume web page if MIME type cannot be determined + data_type="Document", # assume this is not meant for seeAlso + ) + def create_manifest(ingest): """ Create or update a Manifest from supplied metadata and images. @@ -61,7 +82,13 @@ def create_manifest(ingest): else: manifest = Manifest.objects.create() for (key, value) in metadata.items(): - setattr(manifest, key, value) + if key == "related": + # add RelatedLinks from metadata spreadsheet key "related" + create_related_links(manifest, value) + else: + # all other keys should exist as fields on Manifest (for now) + setattr(manifest, key, value) + # TODO: if the key doesn't exist on Manifest model, add it to Manifest.metadata else: manifest = Manifest() @@ -77,9 +104,7 @@ def create_manifest(ingest): manifest.collections.set(ingest.collections.all()) # Save again once relationship is set manifest.save() - - # if type(ingest, .models.Remote): - if isinstance(ingest, Remote): + else: RelatedLink( manifest=manifest, link=ingest.remote_url, diff --git a/apps/ingest/tasks.py b/apps/ingest/tasks.py index 6b5458b23..91202aab3 100644 --- a/apps/ingest/tasks.py +++ b/apps/ingest/tasks.py @@ -17,7 +17,7 @@ from apps.ingest.models import IngestTaskWatcher from .mail import send_email_on_failure, send_email_on_success -from .services import create_manifest +from .services import create_manifest, create_related_links # Use `apps.get_model` to avoid circular import error. Because the parameters used to # create a background task have to be serializable, we can't just pass in the model object. @@ -129,7 +129,12 @@ def create_canvases_from_s3_ingest(metadata, ingest_id): except Manifest.DoesNotExist: manifest = Manifest.objects.create(pid=pid) for (key, value) in metadata.items(): - setattr(manifest, key, value) + if key == "related": + # add RelatedLinks from metadata spreadsheet key "related" + create_related_links(manifest, value) + else: + # all other keys should exist as fields on Manifest (for now) + setattr(manifest, key, value) # Image server: set from ingest ingest = S3Ingest.objects.get(pk=ingest_id) manifest.image_server = ingest.image_server diff --git a/apps/ingest/tests/test_local.py b/apps/ingest/tests/test_local.py index 2d7a0a4b9..5cfdb6cab 100644 --- a/apps/ingest/tests/test_local.py +++ b/apps/ingest/tests/test_local.py @@ -331,6 +331,23 @@ def test_it_creates_mainfest_with_metadata_property(self): assert local.manifest.pid == '808' assert local.manifest.title == 'Goodie Mob' + def test_create_related_links(self): + metadata = { + 'pid': '808', + 'related': 'https://github.com/ecds/readux/tree/develop;https://archive.org/download/cherokeehymnbook00boud/cherokeehymnbook00boud.pdf' + } + local = self.mock_local('no_meta_file.zip', metadata=metadata) + local.manifest = create_manifest(local) + related_links = local.manifest.related_links + # should get 2 from metadata, 1 from volume url + assert len(related_links) == 3 + # should get github link format as text/html + assert any([link["@id"] == "https://github.com/ecds/readux/tree/develop" for link in related_links]) + assert any([link["format"] == "text/html" for link in related_links]) + # should get pdf format too + assert any([link["@id"] == "https://archive.org/download/cherokeehymnbook00boud/cherokeehymnbook00boud.pdf" for link in related_links]) + assert any([link["format"] == "application/pdf" for link in related_links]) + def test_moving_bulk_bundle_to_s3(self): """ It should upload Local.bundle_from_bulk to mock S3 by saving it to From 6990da879b82eca570c1be77cd9d3c0e8d45dc04 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 12:56:13 -0500 Subject: [PATCH 05/10] Fix failing test: check any, not first (#958) --- apps/ingest/tests/test_services.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ingest/tests/test_services.py b/apps/ingest/tests/test_services.py index d141b64cc..1273e77ae 100644 --- a/apps/ingest/tests/test_services.py +++ b/apps/ingest/tests/test_services.py @@ -90,8 +90,8 @@ def test_adding_related_link_to_remote_ingest_manifest(self): remote_url='https://swoop.net/manifest.json' # pylint: disable=line-too-long ) manifest = services.create_manifest(remote) - related_link = manifest.relatedlink_set.first() - assert related_link.link == remote.remote_url + related_links = manifest.relatedlink_set.all() + assert any([link.link == remote.remote_url for link in related_links]) httpretty.disable() From 1e057a3875c998baa2b9ab3b142cfa6b80721574 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 14:46:00 -0500 Subject: [PATCH 06/10] Fix RelatedLink uuid errors on save/change --- apps/iiif/manifests/admin.py | 2 ++ .../migrations/0059_alter_relatedlink_id.py | 20 +++++++++++++++++++ apps/iiif/manifests/models.py | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py diff --git a/apps/iiif/manifests/admin.py b/apps/iiif/manifests/admin.py index ff697617e..6a39b171b 100644 --- a/apps/iiif/manifests/admin.py +++ b/apps/iiif/manifests/admin.py @@ -1,6 +1,7 @@ """Django admin module for maninfests""" from django.contrib import admin from django.http import HttpResponseRedirect +from django.http.request import HttpRequest from django.urls.conf import path from import_export import resources, fields from import_export.admin import ImportExportModelAdmin @@ -35,6 +36,7 @@ class Meta: # pylint: disable=too-few-public-methods, missing-class-docstring class RelatedLinksInline(admin.TabularInline): model = RelatedLink + exclude = ("id",) fields = ( "link", "data_type", diff --git a/apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py b/apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py new file mode 100644 index 000000000..20629c976 --- /dev/null +++ b/apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2023-12-05 19:41 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("manifests", "0058_alter_relatedlink_format_and_data_type"), + ] + + operations = [ + migrations.AlterField( + model_name="relatedlink", + name="id", + field=models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ] diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index 614efbf53..31c716006 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -368,7 +368,7 @@ class Note(models.Model): class RelatedLink(models.Model): """ Links to related resources """ - id = models.UUIDField(primary_key=True, default=uuid4) + id = models.UUIDField(primary_key=True, default=uuid4, editable=False) link = models.CharField(max_length=255) data_type = models.CharField( max_length=255, From 2554c08428339507bac493db995bcfc451df56a6 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 14:50:00 -0500 Subject: [PATCH 07/10] Add external links and seeAlso to sidebar (#959) --- apps/iiif/manifests/models.py | 21 +++++++++++++++++++++ apps/templates/page.html | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index 31c716006..20cb85d0e 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -272,6 +272,27 @@ def related_links(self): }) return links + @property + def external_links(self): + """Dict of lists of external links for display on volume pages + + :return: Dict of external links ("related" and "seeAlso") + :rtype: dict + """ + related_links = self.relatedlink_set.all() + return { + "see_also": [ + link.link + for link in related_links + if link.data_type.lower() == "dataset" + ], + "related": [ + link.link + for link in related_links + if link.data_type.lower() != "dataset" + ], + } + @property def see_also_links(self): """List of links for IIIF v2 'seeAlso' field (structured data). diff --git a/apps/templates/page.html b/apps/templates/page.html index 9df5932b7..b07f083be 100644 --- a/apps/templates/page.html +++ b/apps/templates/page.html @@ -430,6 +430,25 @@

Text

{% endif %} + + {% if volume.external_links.see_also %} + + {% for link in volume.external_links.see_also %} + + + {% endfor %} + + {% endif %} + + {% if volume.external_links.related %} + + {% for link in volume.external_links.related %} + + + {% endfor %} + + {% endif %} + From e8ef16dd6b810540cc4de13a36932937a27cde0e Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 14:50:08 -0500 Subject: [PATCH 08/10] Exclude internal links from external link property #959 --- apps/iiif/manifests/models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index 20cb85d0e..f5d5cc85c 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -279,7 +279,11 @@ def external_links(self): :return: Dict of external links ("related" and "seeAlso") :rtype: dict """ - related_links = self.relatedlink_set.all() + # exclude internal links from related link set + related_links = self.relatedlink_set.exclude( + link__icontains=settings.HOSTNAME + ) + # dict keys correspond to headings in sidebar return { "see_also": [ link.link From 60f3862c7095e9bfc371aac2b9aab886e594ef36 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 15:06:52 -0500 Subject: [PATCH 09/10] Use boolean is_structured_data, not data_type for seeAlso (#958) --- apps/iiif/manifests/admin.py | 2 +- .../0060_relatedlink_is_structured_data.py | 38 +++++++++++++++++++ apps/iiif/manifests/models.py | 34 ++++++++--------- apps/iiif/manifests/tests/tests.py | 2 +- apps/ingest/services.py | 5 ++- 5 files changed, 60 insertions(+), 21 deletions(-) create mode 100644 apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py diff --git a/apps/iiif/manifests/admin.py b/apps/iiif/manifests/admin.py index 6a39b171b..50288374c 100644 --- a/apps/iiif/manifests/admin.py +++ b/apps/iiif/manifests/admin.py @@ -39,7 +39,7 @@ class RelatedLinksInline(admin.TabularInline): exclude = ("id",) fields = ( "link", - "data_type", + "is_structured_data", "format", ) extra = 1 diff --git a/apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py b/apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py new file mode 100644 index 000000000..dfaea8442 --- /dev/null +++ b/apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.12 on 2023-12-05 19:59 + +from django.db import migrations, models + + +def populate_is_structured_data(apps, schema_editor): + # Data migration to populate RelatedLink.is_structured_data for existing data + RelatedLink = apps.get_model("manifests", "RelatedLink") + rl_set = RelatedLink.objects.all() + for rl in rl_set: + # Assume all existing RelatedLinks are structured data, since they were previously only + # being added in Remote ingests when there was an existing manifest (which is structured + # data) + rl.is_structured_data = True + RelatedLink.objects.bulk_update(rl_set, ["is_structured_data"], batch_size=1000) + + +class Migration(migrations.Migration): + dependencies = [ + ("manifests", "0059_alter_relatedlink_id"), + ] + + operations = [ + migrations.AddField( + model_name="relatedlink", + name="is_structured_data", + field=models.BooleanField( + default=False, + help_text="True if this link is structured data that should appear in the manifest's 'seeAlso' field; if false, the link will appear in the 'related' field instead. Leave unchecked if unsure.", + ), + ), + migrations.AlterField( + model_name="relatedlink", + name="data_type", + field=models.CharField(default="Dataset", max_length=255), + ), + migrations.RunPython(populate_is_structured_data, migrations.RunPython.noop), + ] diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index f5d5cc85c..f54711038 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -288,12 +288,12 @@ def external_links(self): "see_also": [ link.link for link in related_links - if link.data_type.lower() == "dataset" + if link.is_structured_data ], "related": [ link.link for link in related_links - if link.data_type.lower() != "dataset" + if not link.is_structured_data ], } @@ -304,18 +304,15 @@ def see_also_links(self): :return: List of links to structured data describing Manifest :rtype: list """ - links = [] - for link in self.relatedlink_set.all(): - if link.data_type.lower() == "dataset": - links.append( - { - "@id": link.link, - "format": link.format, - } - if link.format - else link.link - ) - return links + return [ + { + "@id": link.link, + "format": link.format, + } + if link.format + else link.link + for link in self.relatedlink_set.filter(is_structured_data=True) + ] # TODO: Is this needed? It doesn't seem to be called anywhere. # Could we just use the label as is? @@ -398,9 +395,12 @@ class RelatedLink(models.Model): data_type = models.CharField( max_length=255, default='Dataset', - help_text="Leave as 'Dataset' for structured data describing this document (e.g. a " + - "remote manifest) and this link will appear in 'seeAlso'; change to any other value and " + - "it will only appear in the 'related' property of the manifest.", + ) + is_structured_data = models.BooleanField( + default=False, + help_text="True if this link is structured data that should appear in the manifest's " + + "'seeAlso' field; if false, the link will appear in the 'related' field instead. Leave " + + "unchecked if unsure.", ) label = GenericRelation(ValueByLanguage) format = models.CharField(max_length=255, choices=Choices.MIMETYPES, blank=True, null=True) diff --git a/apps/iiif/manifests/tests/tests.py b/apps/iiif/manifests/tests/tests.py index 16be42f34..42ffed926 100644 --- a/apps/iiif/manifests/tests/tests.py +++ b/apps/iiif/manifests/tests/tests.py @@ -177,7 +177,7 @@ def test_serialized_related_links(self): ) assert not no_links['seeAlso'] - link = RelatedLink(link='images.org', manifest=manifest) + link = RelatedLink(link='images.org', manifest=manifest, is_structured_data=True) link.save() manifest.refresh_from_db() diff --git a/apps/ingest/services.py b/apps/ingest/services.py index 365283dff..47f829d33 100644 --- a/apps/ingest/services.py +++ b/apps/ingest/services.py @@ -58,7 +58,7 @@ def create_related_links(manifest, related_str): manifest=manifest, link=link, format=format or "text/html", # assume web page if MIME type cannot be determined - data_type="Document", # assume this is not meant for seeAlso + is_structured_data=False, # assume this is not meant for seeAlso ) def create_manifest(ingest): @@ -108,7 +108,8 @@ def create_manifest(ingest): RelatedLink( manifest=manifest, link=ingest.remote_url, - format='application/ld+json' + format='application/ld+json', + is_structured_data=True, ).save() return manifest From b2bde2837197392a5e4ed6f877eea287ae3d6715 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 5 Dec 2023 15:23:52 -0500 Subject: [PATCH 10/10] Squash manifests RelatedLink migrations --- ...ured_data.py => 0058_alter_relatedlink.py} | 35 +++++++++++++---- ..._alter_relatedlink_format_and_data_type.py | 39 ------------------- .../migrations/0059_alter_relatedlink_id.py | 20 ---------- 3 files changed, 28 insertions(+), 66 deletions(-) rename apps/iiif/manifests/migrations/{0060_relatedlink_is_structured_data.py => 0058_alter_relatedlink.py} (58%) delete mode 100644 apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py delete mode 100644 apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py diff --git a/apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py b/apps/iiif/manifests/migrations/0058_alter_relatedlink.py similarity index 58% rename from apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py rename to apps/iiif/manifests/migrations/0058_alter_relatedlink.py index dfaea8442..cdb82b69d 100644 --- a/apps/iiif/manifests/migrations/0060_relatedlink_is_structured_data.py +++ b/apps/iiif/manifests/migrations/0058_alter_relatedlink.py @@ -1,6 +1,7 @@ -# Generated by Django 3.2.12 on 2023-12-05 19:59 +# Generated by Django 3.2.12 on 2023-12-05 16:16 from django.db import migrations, models +import uuid def populate_is_structured_data(apps, schema_editor): @@ -17,10 +18,35 @@ def populate_is_structured_data(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ("manifests", "0059_alter_relatedlink_id"), + ("manifests", "0057_alter_manifest_languages"), ] operations = [ + migrations.AlterField( + model_name="relatedlink", + name="id", + field=models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + migrations.AlterField( + model_name="relatedlink", + name="format", + field=models.CharField( + blank=True, + choices=[ + ("text/html", "HTML or web page"), + ("application/json", "JSON"), + ("application/ld+json", "JSON-LD"), + ("application/pdf", "PDF"), + ("text/plain", "Text"), + ("application/xml", "XML"), + ("application/octet-stream", "Other"), + ], + max_length=255, + null=True, + ), + ), migrations.AddField( model_name="relatedlink", name="is_structured_data", @@ -29,10 +55,5 @@ class Migration(migrations.Migration): help_text="True if this link is structured data that should appear in the manifest's 'seeAlso' field; if false, the link will appear in the 'related' field instead. Leave unchecked if unsure.", ), ), - migrations.AlterField( - model_name="relatedlink", - name="data_type", - field=models.CharField(default="Dataset", max_length=255), - ), migrations.RunPython(populate_is_structured_data, migrations.RunPython.noop), ] diff --git a/apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py b/apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py deleted file mode 100644 index 875e79d25..000000000 --- a/apps/iiif/manifests/migrations/0058_alter_relatedlink_format_and_data_type.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 3.2.12 on 2023-12-05 16:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ("manifests", "0057_alter_manifest_languages"), - ] - - operations = [ - migrations.AlterField( - model_name="relatedlink", - name="data_type", - field=models.CharField( - default="Dataset", - help_text="Leave as 'Dataset' for structured data describing this document (e.g. a remote manifest) and this link will appear in 'seeAlso'; change to any other value and it will only appear in the 'related' property of the manifest.", - max_length=255, - ), - ), - migrations.AlterField( - model_name="relatedlink", - name="format", - field=models.CharField( - blank=True, - choices=[ - ("text/html", "HTML or web page"), - ("application/json", "JSON"), - ("application/ld+json", "JSON-LD"), - ("application/pdf", "PDF"), - ("text/plain", "Text"), - ("application/xml", "XML"), - ("application/octet-stream", "Other"), - ], - max_length=255, - null=True, - ), - ), - ] diff --git a/apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py b/apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py deleted file mode 100644 index 20629c976..000000000 --- a/apps/iiif/manifests/migrations/0059_alter_relatedlink_id.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.2.12 on 2023-12-05 19:41 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - dependencies = [ - ("manifests", "0058_alter_relatedlink_format_and_data_type"), - ] - - operations = [ - migrations.AlterField( - model_name="relatedlink", - name="id", - field=models.UUIDField( - default=uuid.uuid4, editable=False, primary_key=True, serialize=False - ), - ), - ]