From 6e67dcc0b9fea92edad12b30d8fe3ef29cde5e4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Anton=20M=C3=BCller?=
Date: Wed, 6 Nov 2024 10:39:06 +0100
Subject: [PATCH 1/4] Kleinigkeiten
---
dumper/templates/dumper/about.html | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/dumper/templates/dumper/about.html b/dumper/templates/dumper/about.html
index 4cb202e..d3e1348 100644
--- a/dumper/templates/dumper/about.html
+++ b/dumper/templates/dumper/about.html
@@ -456,13 +456,11 @@ URIs
Eine Konkordanz zwischen PMB-URIs und GND-URIs kann über folgende BEACON Datei bezogen werden.
Eine Konkordanz zwischen PMB-URIs und Wikidata-URIs kann über folgende BEACON Datei bezogen werden.
- Wikipedia-Einträge werden nicht direkt verlinkt. Auf der linken Seite im Menü eines Wikipedia-Eintrags
- steht ein Link auf das entsprechende Wikidata-Objekt.
+ href="{% url 'apis_core:wikidata_beacon' %}">BEACON Datei bezogen werden. (Über Wikidata ist auch die Verlinkung zur Wikipedia sichergestellt.)
Konkordanz-Listen zwischen Projekt-URIS und PMB-URIs können nach diesem Schema heruntergeladen werden: https://pmb.acdh.oeaw.ac.at/apis/domain-uris/{projekt-uri-domain}
, also z.B:
Zur Personensuche
@@ -487,8 +485,10 @@ Berlin
Adressbuch Berlin
+ Deutsche Digitale Bibliothek
The European Library
- (Internationale Zeitungen, auch Berlin.)
+ (Internationale Zeitungen)
+
{% endblock %}
\ No newline at end of file
From e86bb2beabb3513ff40af5c0c937356139fe4af7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Anton=20M=C3=BCller?=
Date: Wed, 6 Nov 2024 10:56:18 +0100
Subject: [PATCH 2/4] Brahms, Hanslick, Schubert, Schnitzler-Kino
---
dumper/templates/dumper/about.html | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/dumper/templates/dumper/about.html b/dumper/templates/dumper/about.html
index d3e1348..8e90ceb 100644
--- a/dumper/templates/dumper/about.html
+++ b/dumper/templates/dumper/about.html
@@ -35,6 +35,16 @@ Alexander Wilfing, Christoph Landerer: Hanslick-Online, https://hanslick.acdh.oeaw.ac.at/.
+ 2.385 Entitäten (Oktober 2024)
+ Vasiliki Papadopoulou und Monika Jaroš: Brahms online, https://brahms-online.oeaw.ac.at/.
+ 687 Entitäten (Oktober 2024)
+ Schubert digital, https://schubert-digital.at/.
+ 358 Entitäten (Oktober 2024)
+ Stephan Kurz und Daniel Schopper: Kinobesuche von Clara Katharina Pollaczek und Arthur Schnitzler
+ 820 Entitäten (November 2024)
+
+
Die Entitäten werden kontinuierlich erweitert, durchgesehen und auch miteinander in Beziehung
gesetzt.
From 8198c6c35e8afbab6f81884d64b6a0f5023e609c Mon Sep 17 00:00:00 2001
From: csae8092
Date: Wed, 6 Nov 2024 12:40:58 +0100
Subject: [PATCH 3/4] closes the huge relations import-sheet
arthur-schnitzler/pmb-service closes #228
---
apis_core/apis_relations/utils.py | 2 +
.../issue__228-huge-relation-import.ipynb | 210 ++++++++++++++++++
2 files changed, 212 insertions(+)
create mode 100644 notebooks/issue__228-huge-relation-import.ipynb
diff --git a/apis_core/apis_relations/utils.py b/apis_core/apis_relations/utils.py
index fe7e126..ddf48c5 100644
--- a/apis_core/apis_relations/utils.py
+++ b/apis_core/apis_relations/utils.py
@@ -143,6 +143,7 @@ class Meta:
"relation_type",
"start_date__year",
"end_date__year",
+ "collection",
]
return MyRelationsListFilter
@@ -163,6 +164,7 @@ def __init__(self, *args, **kwargs):
"relation_type",
"start_date__year",
"end_date__year",
+ "collection",
)
return MyRelationsFilterFormHelper
diff --git a/notebooks/issue__228-huge-relation-import.ipynb b/notebooks/issue__228-huge-relation-import.ipynb
new file mode 100644
index 0000000..813b28e
--- /dev/null
+++ b/notebooks/issue__228-huge-relation-import.ipynb
@@ -0,0 +1,210 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "abdba1e8-027e-4931-a35b-03aaf8aa9464",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# run against production 2024-11-06\n",
+ "from django.core.exceptions import ObjectDoesNotExist\n",
+ "from tqdm import tqdm\n",
+ "from dumper.utils import gsheet_to_df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cdb36196-46aa-4b7b-9871-0a8a3dd279ea",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = gsheet_to_df(\"1-_WXbdmpLzz_9vBiZ1y9v2tle_26m4tAhPTGzkkin5E\")\n",
+ "col, _= Collection.objects.get_or_create(name=\"Schnitzler-Veranstaltungen\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "682d2d62-1e30-4db5-8323-c07a3f62222e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.head(3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "342c4e3d-39c5-4f8b-b0b0-950cde457983",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "relation_type_lookup = {\n",
+ " \"1049\": {\n",
+ " \"relation_type\":PersonWork,\n",
+ " \"relation\": PersonWorkRelation.objects.get(id=1049),\n",
+ " \"source_class\": Person,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1181\": {\n",
+ " \"relation_type\": PersonPlace,\n",
+ " \"relation\": PersonPlaceRelation.objects.get(id=1181),\n",
+ " \"source_class\": Person,\n",
+ " \"target_class\": Place,\n",
+ " },\n",
+ " \"1201\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=1201),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1204\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=1204),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1206\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=1206),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1224\": {\n",
+ " \"relation_type\": PersonWork,\n",
+ " \"relation\": PersonWorkRelation.objects.get(id=1224),\n",
+ " \"source_class\": Person,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1252\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=1252),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1256\": {\n",
+ " \"relation_type\": PersonEvent,\n",
+ " \"relation\": PersonEventRelation.objects.get(id=1256),\n",
+ " \"source_class\": Person,\n",
+ " \"target_class\": Event,\n",
+ " },\n",
+ " \"1351\": {\n",
+ " \"relation_type\": InstitutionEvent,\n",
+ " \"relation\": InstitutionEventRelation.objects.get(id=1351),\n",
+ " \"source_class\": Institution,\n",
+ " \"target_class\": Event,\n",
+ " },\n",
+ " \"1369\": {\n",
+ " \"relation_type\": PlaceEvent,\n",
+ " \"relation\": PlaceEventRelation.objects.get(id=1369),\n",
+ " \"source_class\": Place,\n",
+ " \"target_class\": Event,\n",
+ " },\n",
+ " \"1369\": {\n",
+ " \"relation_type\": PlaceEvent,\n",
+ " \"relation\": PlaceEventRelation.objects.get(id=1369),\n",
+ " \"source_class\": Place,\n",
+ " \"target_class\": Event,\n",
+ " },\n",
+ " \"1370\": {\n",
+ " \"relation_type\": PersonEvent,\n",
+ " \"relation\": PersonEventRelation.objects.get(id=1370),\n",
+ " \"source_class\": Person,\n",
+ " \"target_class\": Event,\n",
+ " },\n",
+ " \"1527\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=1527),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"1528\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=1528),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \"4362\": {\n",
+ " \"relation_type\": EventWork,\n",
+ " \"relation\": EventWorkRelation.objects.get(id=4362),\n",
+ " \"source_class\": Event,\n",
+ " \"target_class\": Work,\n",
+ " },\n",
+ " \n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6748b522-2617-4436-ab9b-0c46c1867e6a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "does_not_exist = set()\n",
+ "for g, ndf in df.groupby(\"relation-id\"):\n",
+ " relation = relation_type_lookup[str(g)][\"relation\"]\n",
+ " relation_class = relation_type_lookup[str(g)][\"relation_type\"]\n",
+ " source_class = relation_type_lookup[str(g)][\"source_class\"]\n",
+ " target_class = relation_type_lookup[str(g)][\"target_class\"]\n",
+ " print(relation, relation_class, target_class)\n",
+ " for i, row in tqdm(ndf.iterrows(), total=len(ndf)):\n",
+ " try:\n",
+ " source = source_class.objects.get(pk=int(row[\"source_id\"]))\n",
+ " except (ObjectDoesNotExist, ValueError):\n",
+ " does_not_exist.add(row[\"source_id\"])\n",
+ " continue\n",
+ " try:\n",
+ " target = target_class.objects.get(pk=int(row[\"target_id\"]))\n",
+ " except ObjectDoesNotExist:\n",
+ " does_not_exist.add(row[\"target_id\"])\n",
+ " if isinstance(row[\"relation_start_date_written\"], str):\n",
+ " start_date_written = row[\"relation_start_date_written\"]\n",
+ " end_date_written = row[\"relation_end_date_written\"]\n",
+ " else:\n",
+ " start_date_written = None\n",
+ " end_date_written = None\n",
+ " relation_object = {\n",
+ " relation_class.get_related_entity_field_namea(): source,\n",
+ " relation_class.get_related_entity_field_nameb(): target,\n",
+ " \"relation_type\": relation,\n",
+ " \"start_date_written\": start_date_written,\n",
+ " \"end_date_written\": end_date_written\n",
+ " }\n",
+ " created_relation, _ = relation_class.objects.get_or_create(**relation_object)\n",
+ " created_relation.collection.add(col)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3193d0cb-c5b9-45cc-ad16-ba18843f3a4a",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Django Shell-Plus",
+ "language": "python",
+ "name": "django_extensions"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
From c1a0c71dcb6ea2330d10ee836e719ada21f9facd Mon Sep 17 00:00:00 2001
From: csae8092
Date: Sat, 9 Nov 2024 09:17:37 +0100
Subject: [PATCH 4/4] sort by -ID
---
.flake8 | 2 +-
apis_core/apis_entities/models.py | 24 ++++++++++++++----------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/.flake8 b/.flake8
index f830282..7c90cdd 100644
--- a/.flake8
+++ b/.flake8
@@ -1,5 +1,5 @@
[flake8]
-ignore = D203 W504
+ignore = D203 W504 W503
max-line-length = 120
exclude =
*/migrations,
diff --git a/apis_core/apis_entities/models.py b/apis_core/apis_entities/models.py
index 6e4870d..855f9d7 100644
--- a/apis_core/apis_entities/models.py
+++ b/apis_core/apis_entities/models.py
@@ -103,13 +103,16 @@ def create_relation_methods_from_manytomany_fields(cls):
or
person.get_related_person_instances()
- Note that with these methods it is not necessary to differentiate between A and B entities when self-relations exist.
+ Note that with these methods it is not necessary to differentiate between
+ A and B entities when self-relations exist.
The result of any such method call is the queryset of the related entities.
- (And not a ManyToManyManager as is the case when calling ._set where in the case of self-relation
+ (And not a ManyToManyManager as is the case when calling ._set where
+ in the case of self-relation
it must be differentiated between A and B entities, e.g. person.personA_set )
- It was not possible to my understanding to change managers in such a way that two (the A and the B) could be combined
+ It was not possible to my understanding to change managers in such a way that two
+ (the A and the B) could be combined
into one manager. Hence these additional shortcut methods.
:return: None
@@ -121,7 +124,8 @@ def create_function_from_manytomany_field_to_other_entity(
"""
creates the individual method from a ManyToMany field by calling the manager's objects.all()
- This method creation has to be done here in a separate method, so that it can be called once before assignment
+ This method creation has to be done here in a separate method, so that it can be called once
+ before assignment
as otherwise the variable 'entity_name' in the loop below changes with each iteration and with that also the
method references (due to python's "late binding").
A method call in between thus forces the content of 'entity_name' to be assigned for good to the
@@ -220,7 +224,7 @@ def get_all_entity_classes(cls):
:return: list of all python classes of the entities defined within this models' module
"""
- if cls._all_entity_classes == None:
+ if cls._all_entity_classes is None:
entity_classes = []
entity_names = []
@@ -515,7 +519,7 @@ class Meta:
verbose_name = "Person"
verbose_name_plural = "Personen"
ordering = [
- "id",
+ "-id",
]
def get_tei_url(self):
@@ -550,7 +554,7 @@ class Meta:
verbose_name = "Ort"
verbose_name_plural = "Orte"
ordering = [
- "id",
+ "-id",
]
def get_tei_url(self):
@@ -577,7 +581,7 @@ class Meta:
verbose_name = "Institution"
verbose_name_plural = "Institutionen"
ordering = [
- "id",
+ "-id",
]
def get_tei_url(self):
@@ -604,7 +608,7 @@ class Meta:
verbose_name = "Ereignis"
verbose_name_plural = "Ereignisse"
ordering = [
- "id",
+ "-id",
]
def get_tei_url(self):
@@ -629,7 +633,7 @@ class Meta:
verbose_name = "Werk"
verbose_name_plural = "Werke"
ordering = [
- "id",
+ "-id",
]
def get_tei_url(self):