diff --git a/.gitignore b/.gitignore
index e722819..588f399 100644
--- a/.gitignore
+++ b/.gitignore
@@ -189,3 +189,5 @@ node_modules/
featureCodes_en.csv
featureCodes_en.tsv
listperson.xml
+schubert_pmb.csv
+brahms_pmb.csv
diff --git a/apis_core/apis_relations/config.py b/apis_core/apis_relations/config.py
index 222d09e..f77e3ea 100644
--- a/apis_core/apis_relations/config.py
+++ b/apis_core/apis_relations/config.py
@@ -14,20 +14,3 @@
"img_url",
"img_last_checked",
]
-
-
-CRUD_COLUMN = tables.TemplateColumn(
- """
-
-
- Verbindung bearbeiten
-
-
-
-
-
-
- """,
- verbose_name="Ändern, Kopieren oder Löschen",
- orderable=False,
-)
diff --git a/apis_core/apis_relations/event_event_relation_views.py b/apis_core/apis_relations/event_event_relation_views.py
new file mode 100644
index 0000000..5170a56
--- /dev/null
+++ b/apis_core/apis_relations/event_event_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import EventEventRelation
+from apis_core.apis_relations.models import EventEvent
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class EventEventCreate(BaseCreateView):
+
+ model = EventEvent
+ form_class = generate_relation_form(EventEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(EventEventCreate, self).dispatch(*args, **kwargs)
+
+
+class EventEventUpdate(BaseUpdateView):
+
+ model = EventEvent
+ form_class = generate_relation_form(EventEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(EventEventUpdate, self).dispatch(*args, **kwargs)
+
+
+class EventEventListView(GenericListView):
+ model = EventEvent
+ filter_class = generate_relation_filter(EventEvent, EventEventRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(EventEvent)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Ereignisse und Ereignisse"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/event_work_relation_views.py b/apis_core/apis_relations/event_work_relation_views.py
new file mode 100644
index 0000000..e33886f
--- /dev/null
+++ b/apis_core/apis_relations/event_work_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import EventWorkRelation
+from apis_core.apis_relations.models import EventWork
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class EventWorkCreate(BaseCreateView):
+
+ model = EventWork
+ form_class = generate_relation_form(EventWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(EventWorkCreate, self).dispatch(*args, **kwargs)
+
+
+class EventWorkUpdate(BaseUpdateView):
+
+ model = EventWork
+ form_class = generate_relation_form(EventWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(EventWorkUpdate, self).dispatch(*args, **kwargs)
+
+
+class EventWorkListView(GenericListView):
+ model = EventWork
+ filter_class = generate_relation_filter(EventWork, EventWorkRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(EventWork)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Ereignisse und Werke"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/institution_event_relation_views.py b/apis_core/apis_relations/institution_event_relation_views.py
new file mode 100644
index 0000000..3bd03ce
--- /dev/null
+++ b/apis_core/apis_relations/institution_event_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import InstitutionEventRelation
+from apis_core.apis_relations.models import InstitutionEvent
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class InstitutionEventCreate(BaseCreateView):
+
+ model = InstitutionEvent
+ form_class = generate_relation_form(InstitutionEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionEventCreate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionEventUpdate(BaseUpdateView):
+
+ model = InstitutionEvent
+ form_class = generate_relation_form(InstitutionEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionEventUpdate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionEventListView(GenericListView):
+ model = InstitutionEvent
+ filter_class = generate_relation_filter(InstitutionEvent, InstitutionEventRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(InstitutionEvent)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Institutionen und Ereignisse"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/institution_institution_relation_views.py b/apis_core/apis_relations/institution_institution_relation_views.py
new file mode 100644
index 0000000..138cf53
--- /dev/null
+++ b/apis_core/apis_relations/institution_institution_relation_views.py
@@ -0,0 +1,61 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import InstitutionInstitutionRelation
+from apis_core.apis_relations.models import InstitutionInstitution
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class InstitutionInstitutionCreate(BaseCreateView):
+
+ model = InstitutionInstitution
+ form_class = generate_relation_form(InstitutionInstitution)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionInstitutionCreate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionInstitutionUpdate(BaseUpdateView):
+
+ model = InstitutionInstitution
+ form_class = generate_relation_form(InstitutionInstitution)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionInstitutionUpdate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionInstitutionListView(GenericListView):
+ model = InstitutionInstitution
+ filter_class = generate_relation_filter(
+ InstitutionInstitution, InstitutionInstitutionRelation
+ )
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(InstitutionInstitution)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Institutionen und Institutionen"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/institution_place_relation_views.py b/apis_core/apis_relations/institution_place_relation_views.py
new file mode 100644
index 0000000..14bb520
--- /dev/null
+++ b/apis_core/apis_relations/institution_place_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import InstitutionPlaceRelation
+from apis_core.apis_relations.models import InstitutionPlace
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class InstitutionPlaceCreate(BaseCreateView):
+
+ model = InstitutionPlace
+ form_class = generate_relation_form(InstitutionPlace)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionPlaceCreate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionPlaceUpdate(BaseUpdateView):
+
+ model = InstitutionPlace
+ form_class = generate_relation_form(InstitutionPlace)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionPlaceUpdate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionPlaceListView(GenericListView):
+ model = InstitutionPlace
+ filter_class = generate_relation_filter(InstitutionPlace, InstitutionPlaceRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(InstitutionPlace)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Institutionen und Orte"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/institution_work_relation_views.py b/apis_core/apis_relations/institution_work_relation_views.py
new file mode 100644
index 0000000..b1049b8
--- /dev/null
+++ b/apis_core/apis_relations/institution_work_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import InstitutionWorkRelation
+from apis_core.apis_relations.models import InstitutionWork
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class InstitutionWorkCreate(BaseCreateView):
+
+ model = InstitutionWork
+ form_class = generate_relation_form(InstitutionWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionWorkCreate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionWorkUpdate(BaseUpdateView):
+
+ model = InstitutionWork
+ form_class = generate_relation_form(InstitutionWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(InstitutionWorkUpdate, self).dispatch(*args, **kwargs)
+
+
+class InstitutionWorkListView(GenericListView):
+ model = InstitutionWork
+ filter_class = generate_relation_filter(InstitutionWork, InstitutionWorkRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(InstitutionWork)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Institutionen und Werke"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/models.py b/apis_core/apis_relations/models.py
index 29e1119..f10a251 100644
--- a/apis_core/apis_relations/models.py
+++ b/apis_core/apis_relations/models.py
@@ -336,40 +336,110 @@ def get_related_entity_field_nameb(cls):
class PersonPerson(AbstractRelation):
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-people apis-person"
+
+ @classmethod
+ def get_color(self):
+ return "#720e07"
+
@classmethod
def get_listview_url(self):
return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+
+class PersonPlace(AbstractRelation):
+
@classmethod
def get_icon(self):
return "bi bi-people apis-person"
@classmethod
def get_second_icon(self):
- return "bi bi-people apis-person"
+ return "bi bi-map apis-place"
@classmethod
def get_color(self):
return "#720e07"
-
-class PersonPlace(AbstractRelation):
@classmethod
def get_listview_url(self):
return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+
+class PersonInstitution(AbstractRelation):
@classmethod
def get_icon(self):
return "bi bi-people apis-person"
@classmethod
def get_second_icon(self):
- return "bi bi-map apis-place"
+ return "bi bi-building-gear apis-institution"
@classmethod
def get_color(self):
return "#720e07"
+ @classmethod
+ def get_listview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
@classmethod
def get_createview_url(self):
return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
@@ -377,7 +447,7 @@ def get_createview_url(self):
def get_object_list_view(self):
list_url = self.get_listview_url()
main_id = self.get_related_entity_instancea().id
- return f"{list_url}?{self.get_related_entity_field_namea()}={main_id}&sort=-updated"
+ return f"{list_url}?source={main_id}&sort=-updated"
def get_edit_url(self):
return reverse_lazy(
@@ -391,24 +461,60 @@ def get_copy_url(self):
kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
)
-
-class PersonInstitution(AbstractRelation):
- @classmethod
- def get_listview_url(self):
- return None
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class PersonEvent(AbstractRelation):
@classmethod
- def get_listview_url(self):
- return None
+ def get_icon(self):
+ return "bi bi-people apis-person"
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-calendar3 apis-event"
+
+ @classmethod
+ def get_color(self):
+ return "#720e07"
-class PersonWork(AbstractRelation):
@classmethod
def get_listview_url(self):
return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+
+class PersonWork(AbstractRelation):
+
@classmethod
def get_icon(self):
return "bi bi-people apis-person"
@@ -421,6 +527,37 @@ def get_second_icon(self):
def get_color(self):
return "#720e07"
+ @classmethod
+ def get_listview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
#######################################################################
#
@@ -430,27 +567,183 @@ def get_color(self):
class InstitutionInstitution(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-building-gear apis-institution"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-building-gear apis-institution"
+
+ @classmethod
+ def get_color(self):
+ return "#1d3461"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class InstitutionPlace(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-building-gear apis-institution"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi map apis-place"
+
+ @classmethod
+ def get_color(self):
+ return "#1d3461"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class InstitutionEvent(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-building-gear apis-institution"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-calendar3 apis-event"
+
+ @classmethod
+ def get_color(self):
+ return "#1d3461"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class InstitutionWork(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-building-gear apis-institution"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi book apis-work"
+
+ @classmethod
+ def get_color(self):
+ return "#1d3461"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
#######################################################################
@@ -461,21 +754,134 @@ def get_listview_url(self):
class PlacePlace(AbstractRelation):
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-map apis-place"
+
+ @classmethod
+ def get_color(self):
+ return "#5bc0eb"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class PlaceEvent(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-map apis-place"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-calendar3 apis-event"
+
+ @classmethod
+ def get_color(self):
+ return "#5bc0eb"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class PlaceWork(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-map apis-place"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-book apis-work"
+
+ @classmethod
+ def get_color(self):
+ return "#5bc0eb"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
#######################################################################
@@ -486,15 +892,93 @@ def get_listview_url(self):
class EventEvent(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-calendar3 apis-event"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-calendar3 apis-event"
+
+ @classmethod
+ def get_color(self):
+ return "#9bc53d"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
class EventWork(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-calendar3 apis-event"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-book apis-work"
+
+ @classmethod
+ def get_color(self):
+ return "#9bc53d"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
#######################################################################
@@ -505,6 +989,45 @@ def get_listview_url(self):
class WorkWork(AbstractRelation):
+ @classmethod
+ def get_icon(self):
+ return "bi bi-book apis-work"
+
+ @classmethod
+ def get_second_icon(self):
+ return "bi bi-book apis-work"
+
+ @classmethod
+ def get_color(self):
+ return "#ff8600"
+
@classmethod
def get_listview_url(self):
- return None
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}")
+
+ @classmethod
+ def get_createview_url(self):
+ return reverse_lazy(f"apis:apis_relations:{self.__name__.lower()}_create")
+
+ def get_object_list_view(self):
+ list_url = self.get_listview_url()
+ main_id = self.get_related_entity_instancea().id
+ return f"{list_url}?source={main_id}&sort=-updated"
+
+ def get_edit_url(self):
+ return reverse_lazy(
+ f"apis:apis_relations:{self.__class__.__name__.lower()}_edit",
+ kwargs={"pk": self.id},
+ )
+
+ def get_copy_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:copy_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
+
+ def get_delete_url(self):
+ return reverse_lazy(
+ "apis:apis_relations:generic_delete_relation",
+ kwargs={"pk": self.id, "relation_class": self.__class__.__name__.lower()},
+ )
diff --git a/apis_core/apis_relations/person_event_relation_views.py b/apis_core/apis_relations/person_event_relation_views.py
new file mode 100644
index 0000000..fd4eed9
--- /dev/null
+++ b/apis_core/apis_relations/person_event_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import PersonEventRelation
+from apis_core.apis_relations.models import PersonEvent
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class PersonEventCreate(BaseCreateView):
+
+ model = PersonEvent
+ form_class = generate_relation_form(PersonEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonEventCreate, self).dispatch(*args, **kwargs)
+
+
+class PersonEventUpdate(BaseUpdateView):
+
+ model = PersonEvent
+ form_class = generate_relation_form(PersonEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonEventUpdate, self).dispatch(*args, **kwargs)
+
+
+class PersonEventListView(GenericListView):
+ model = PersonEvent
+ filter_class = generate_relation_filter(PersonEvent, PersonEventRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PersonEvent)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Personen und Orte"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/person_institution_relation_views.py b/apis_core/apis_relations/person_institution_relation_views.py
new file mode 100644
index 0000000..6e93b91
--- /dev/null
+++ b/apis_core/apis_relations/person_institution_relation_views.py
@@ -0,0 +1,61 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import PersonInstitutionRelation
+from apis_core.apis_relations.models import PersonInstitution
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class PersonInstitutionCreate(BaseCreateView):
+
+ model = PersonInstitution
+ form_class = generate_relation_form(PersonInstitution)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonInstitutionCreate, self).dispatch(*args, **kwargs)
+
+
+class PersonInstitutionUpdate(BaseUpdateView):
+
+ model = PersonInstitution
+ form_class = generate_relation_form(PersonInstitution)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonInstitutionUpdate, self).dispatch(*args, **kwargs)
+
+
+class PersonInstitutionListView(GenericListView):
+ model = PersonInstitution
+ filter_class = generate_relation_filter(
+ PersonInstitution, PersonInstitutionRelation
+ )
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PersonInstitution)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Personen und Orte"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/person_person_relation_views.py b/apis_core/apis_relations/person_person_relation_views.py
index e385c29..ee3bb75 100644
--- a/apis_core/apis_relations/person_person_relation_views.py
+++ b/apis_core/apis_relations/person_person_relation_views.py
@@ -1,127 +1,59 @@
-from browsing.browsing_utils import GenericListView
-from dal import autocomplete
-from crispy_forms.helper import FormHelper
-from crispy_forms.layout import Layout
-from django.urls import reverse_lazy
-from django_filters import FilterSet, ModelMultipleChoiceFilter, RangeFilter
-import django_tables2 as tables
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
-from apis_core.apis_entities.models import Person
from apis_core.apis_vocabularies.models import PersonPersonRelation
+from apis_core.apis_relations.models import PersonPerson
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
-from .config import FIELDS_TO_EXCLUDE
-from .models import PersonPerson
+class PersonPersonCreate(BaseCreateView):
+ model = PersonPerson
+ form_class = generate_relation_form(PersonPerson)
-class PersonPersonListFilter(FilterSet):
- related_persona = ModelMultipleChoiceFilter(
- queryset=Person.objects.all(),
- help_text="Wähle eine oder mehrere Personen",
- label="Personen",
- widget=autocomplete.Select2Multiple(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "person"},
- ),
- attrs={"data-html": True},
- ),
- )
- related_personb = ModelMultipleChoiceFilter(
- queryset=Person.objects.all(),
- help_text="Wähle einen oder mehrere Persone",
- label="Persone",
- widget=autocomplete.Select2Multiple(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "person"},
- ),
- attrs={"data-html": True},
- ),
- )
- relation_type = ModelMultipleChoiceFilter(
- queryset=PersonPersonRelation.objects.all().order_by("name"),
- label="Art der Beziehung",
- help_text="Mehrfachauswahl möglich",
- )
- start_date__year = RangeFilter(
- label="Anfang (Jahr)",
- )
- end_date__year = RangeFilter(
- label="Ende (Jahr)",
- )
+ def get_success_url(self):
+ return self.object.get_object_list_view()
- class Meta:
- model = PersonPerson
- fields = [
- "related_persona",
- "related_personb",
- "relation_type",
- "start_date__year",
- "end_date__year",
- ]
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonPersonCreate, self).dispatch(*args, **kwargs)
-class PersonPersonFormHelper(FormHelper):
- def __init__(self, *args, **kwargs):
- super(PersonPersonFormHelper, self).__init__(*args, **kwargs)
- self.helper = FormHelper()
- self.form_class = "genericFilterForm"
- self.form_method = "GET"
- self.form_tag = False
- self.layout = Layout(
- "related_persona",
- "related_personb",
- "relation_type",
- "start_date__year",
- "end_date__year",
- )
+class PersonPersonUpdate(BaseUpdateView):
+ model = PersonPerson
+ form_class = generate_relation_form(PersonPerson)
-class PersonPersonTable(tables.Table):
- related_persona = tables.TemplateColumn(
- """{{ record.related_persona }}""",
- verbose_name="Person",
- )
- related_personb = tables.TemplateColumn(
- """{{ record.related_personb }}""",
- verbose_name="Person",
- )
- relation_type = tables.TemplateColumn(
- "{{ record.relation_type }}", verbose_name="Art der Beziehung"
- )
- start_date_written = tables.TemplateColumn(
- "{% if record.start_date_written %} {{ record.start_date_written }} {% endif %}",
- verbose_name="Start",
- )
- end_date_written = tables.TemplateColumn(
- "{% if record.end_date_written %} {{ record.end_date_written }} {% endif %}",
- verbose_name="End",
- )
+ def get_success_url(self):
+ return self.object.get_object_list_view()
- class Meta:
- model = PersonPerson
- sequence = (
- "id",
- "related_persona",
- "relation_type",
- "related_personb",
- "start_date_written",
- )
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonPersonUpdate, self).dispatch(*args, **kwargs)
class PersonPersonListView(GenericListView):
model = PersonPerson
- filter_class = PersonPersonListFilter
- formhelper_class = PersonPersonFormHelper
- table_class = PersonPersonTable
+ filter_class = generate_relation_filter(PersonPerson, PersonPersonRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PersonPerson)
init_columns = [
"start_date_written",
"end_date_written",
- "related_persona",
+ "source",
"relation_type",
- "related_personb",
+ "target",
+ "crud",
]
- verbose_name = "Personen und Personen"
+ verbose_name = "Personen und Orte"
exclude_columns = FIELDS_TO_EXCLUDE
enable_merge = False
template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/person_place_relation_views.py b/apis_core/apis_relations/person_place_relation_views.py
index 9bba018..c24fe63 100644
--- a/apis_core/apis_relations/person_place_relation_views.py
+++ b/apis_core/apis_relations/person_place_relation_views.py
@@ -1,65 +1,23 @@
-from django import forms
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
-from django.urls import reverse_lazy
from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
-from dal import autocomplete
-from crispy_forms.helper import FormHelper
-from crispy_forms.layout import Layout, Submit
-from django_filters import FilterSet, ModelMultipleChoiceFilter, RangeFilter
-import django_tables2 as tables
-from apis_core.apis_entities.models import Person, Place
from apis_core.apis_vocabularies.models import PersonPlaceRelation
-
-from .models import PersonPlace
-from .config import FIELDS_TO_EXCLUDE, CRUD_COLUMN
-
-
-class PersonPlaceForm(forms.ModelForm):
-
- class Meta:
- model = PersonPlace
- exclude = FIELDS_TO_EXCLUDE + [
- "collection",
- ]
- widgets = {
- "related_person": autocomplete.ModelSelect2(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "person"},
- ),
- attrs={"data-html": True},
- ),
- "related_place": autocomplete.ModelSelect2(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "place"},
- ),
- attrs={"data-html": True},
- ),
- }
-
- def __init__(self, *args, **kwargs):
- super(PersonPlaceForm, self).__init__(*args, **kwargs)
- self.helper = FormHelper()
- self.helper.form_tag = True
- self.fields["related_person"].required = True
- self.fields["related_place"].required = True
- self.fields["relation_type"].required = True
- self.helper.form_class = "form-horizontal"
- self.helper.label_class = "col-md-3"
- self.helper.field_class = "col-md-9"
- self.helper.add_input(
- Submit("submit", "save"),
- )
+from apis_core.apis_relations.models import PersonPlace
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
class PersonPlaceCreate(BaseCreateView):
model = PersonPlace
- form_class = PersonPlaceForm
+ form_class = generate_relation_form(PersonPlace)
def get_success_url(self):
return self.object.get_object_list_view()
@@ -72,7 +30,7 @@ def dispatch(self, *args, **kwargs):
class PersonPlaceUpdate(BaseUpdateView):
model = PersonPlace
- form_class = PersonPlaceForm
+ form_class = generate_relation_form(PersonPlace)
def get_success_url(self):
return self.object.get_object_list_view()
@@ -82,118 +40,17 @@ def dispatch(self, *args, **kwargs):
return super(PersonPlaceUpdate, self).dispatch(*args, **kwargs)
-class PersonPlaceListFilter(FilterSet):
- related_person = ModelMultipleChoiceFilter(
- queryset=Person.objects.all(),
- help_text="Wähle eine oder mehrere Personen",
- label="Personen",
- widget=autocomplete.Select2Multiple(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "person"},
- ),
- attrs={"data-html": True},
- ),
- )
- related_place = ModelMultipleChoiceFilter(
- queryset=Place.objects.all(),
- help_text="Wähle einen oder mehrere Orte",
- label="Orte",
- widget=autocomplete.Select2Multiple(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "place"},
- ),
- attrs={"data-html": True},
- ),
- )
- relation_type = ModelMultipleChoiceFilter(
- queryset=PersonPlaceRelation.objects.all().order_by("name"),
- label="Art der Beziehung",
- help_text="Mehrfachauswahl möglich",
- )
- start_date__year = RangeFilter(
- label="Anfang (Jahr)",
- )
- end_date__year = RangeFilter(
- label="Ende (Jahr)",
- )
-
- class Meta:
- model = PersonPlace
- fields = [
- "related_person",
- "related_place",
- "relation_type",
- "start_date__year",
- "end_date__year",
- ]
-
-
-class PersonPlaceFormHelper(FormHelper):
- def __init__(self, *args, **kwargs):
- super(PersonPlaceFormHelper, self).__init__(*args, **kwargs)
- self.helper = FormHelper()
- self.form_class = "genericFilterForm"
- self.form_method = "GET"
- self.form_tag = False
- self.layout = Layout(
- "related_person",
- "related_place",
- "relation_type",
- "start_date__year",
- "end_date__year",
- )
-
-
-class PersonPlaceTable(tables.Table):
- related_person = tables.TemplateColumn(
- """
- {{ record.related_person }}
- """,
- verbose_name="Person",
- )
- related_place = tables.TemplateColumn(
- """{{ record.related_place }}""",
- verbose_name="Ort",
- )
- relation_type = tables.TemplateColumn(
- "{{ record.relation_type }}", verbose_name="Art der Beziehung"
- )
- start_date_written = tables.TemplateColumn(
- "{% if record.start_date_written %} {{ record.start_date_written }} {% endif %}",
- verbose_name="Start",
- )
- end_date_written = tables.TemplateColumn(
- "{% if record.end_date_written %} {{ record.end_date_written }} {% endif %}",
- verbose_name="End",
- )
- crud = CRUD_COLUMN
-
- class Meta:
- model = PersonPlace
- sequence = (
- "id",
- "related_person",
- "relation_type",
- "related_place",
- "start_date_written",
- "end_date_written",
- "crud",
- )
-
-
class PersonPlaceListView(GenericListView):
model = PersonPlace
- filter_class = PersonPlaceListFilter
- formhelper_class = PersonPlaceFormHelper
- table_class = PersonPlaceTable
+ filter_class = generate_relation_filter(PersonPlace, PersonPlaceRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PersonPlace)
init_columns = [
"start_date_written",
"end_date_written",
- "related_person",
+ "source",
"relation_type",
- "related_place",
+ "target",
"crud",
]
verbose_name = "Personen und Orte"
diff --git a/apis_core/apis_relations/person_work_relation_views.py b/apis_core/apis_relations/person_work_relation_views.py
index 74b0f02..36ec738 100644
--- a/apis_core/apis_relations/person_work_relation_views.py
+++ b/apis_core/apis_relations/person_work_relation_views.py
@@ -1,127 +1,59 @@
-from browsing.browsing_utils import GenericListView
-from dal import autocomplete
-from crispy_forms.helper import FormHelper
-from crispy_forms.layout import Layout
-from django.urls import reverse_lazy
-from django_filters import FilterSet, ModelMultipleChoiceFilter, RangeFilter
-import django_tables2 as tables
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
-from apis_core.apis_entities.models import Person, Work
from apis_core.apis_vocabularies.models import PersonWorkRelation
+from apis_core.apis_relations.models import PersonWork
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
-from .config import FIELDS_TO_EXCLUDE
-from .models import PersonWork
+class PersonWorkCreate(BaseCreateView):
+ model = PersonWork
+ form_class = generate_relation_form(PersonWork)
-class PersonWorkListFilter(FilterSet):
- related_person = ModelMultipleChoiceFilter(
- queryset=Person.objects.all(),
- help_text="Wähle eine oder mehrere Personen",
- label="Personen",
- widget=autocomplete.Select2Multiple(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "person"},
- ),
- attrs={"data-html": True},
- ),
- )
- related_work = ModelMultipleChoiceFilter(
- queryset=Work.objects.all(),
- help_text="Wähle einen oder mehrere Werke",
- label="Werke",
- widget=autocomplete.Select2Multiple(
- url=reverse_lazy(
- "apis:apis_entities:generic_entities_autocomplete",
- kwargs={"entity": "work"},
- ),
- attrs={"data-html": True},
- ),
- )
- relation_type = ModelMultipleChoiceFilter(
- queryset=PersonWorkRelation.objects.all().order_by("name"),
- label="Art der Beziehung",
- help_text="Mehrfachauswahl möglich",
- )
- start_date__year = RangeFilter(
- label="Anfang (Jahr)",
- )
- end_date__year = RangeFilter(
- label="Ende (Jahr)",
- )
+ def get_success_url(self):
+ return self.object.get_object_list_view()
- class Meta:
- model = PersonWork
- fields = [
- "related_person",
- "related_work",
- "relation_type",
- "start_date__year",
- "end_date__year",
- ]
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonWorkCreate, self).dispatch(*args, **kwargs)
-class PersonWorkFormHelper(FormHelper):
- def __init__(self, *args, **kwargs):
- super(PersonWorkFormHelper, self).__init__(*args, **kwargs)
- self.helper = FormHelper()
- self.form_class = "genericFilterForm"
- self.form_method = "GET"
- self.form_tag = False
- self.layout = Layout(
- "related_person",
- "related_work",
- "relation_type",
- "start_date__year",
- "end_date__year",
- )
+class PersonWorkUpdate(BaseUpdateView):
+ model = PersonWork
+ form_class = generate_relation_form(PersonWork)
-class PersonWorkTable(tables.Table):
- related_person = tables.TemplateColumn(
- """{{ record.related_person }}""",
- verbose_name="Person",
- )
- related_work = tables.TemplateColumn(
- """{{ record.related_work }}""",
- verbose_name="Werk",
- )
- relation_type = tables.TemplateColumn(
- "{{ record.relation_type }}", verbose_name="Art der Beziehung"
- )
- start_date_written = tables.TemplateColumn(
- "{% if record.start_date_written %} {{ record.start_date_written }} {% endif %}",
- verbose_name="Start",
- )
- end_date_written = tables.TemplateColumn(
- "{% if record.end_date_written %} {{ record.end_date_written }} {% endif %}",
- verbose_name="End",
- )
+ def get_success_url(self):
+ return self.object.get_object_list_view()
- class Meta:
- model = PersonWork
- sequence = (
- "id",
- "related_person",
- "relation_type",
- "related_work",
- "start_date_written",
- )
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PersonWorkUpdate, self).dispatch(*args, **kwargs)
class PersonWorkListView(GenericListView):
model = PersonWork
- filter_class = PersonWorkListFilter
- formhelper_class = PersonWorkFormHelper
- table_class = PersonWorkTable
+ filter_class = generate_relation_filter(PersonWork, PersonWorkRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PersonWork)
init_columns = [
"start_date_written",
"end_date_written",
- "related_person",
+ "source",
"relation_type",
- "related_work",
+ "target",
+ "crud",
]
- verbose_name = "Personen und Werke"
+ verbose_name = "Personen und Orte"
exclude_columns = FIELDS_TO_EXCLUDE
enable_merge = False
template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/place_event_relation_views.py b/apis_core/apis_relations/place_event_relation_views.py
new file mode 100644
index 0000000..bb21138
--- /dev/null
+++ b/apis_core/apis_relations/place_event_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import PlaceEventRelation
+from apis_core.apis_relations.models import PlaceEvent
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class PlaceEventCreate(BaseCreateView):
+
+ model = PlaceEvent
+ form_class = generate_relation_form(PlaceEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PlaceEventCreate, self).dispatch(*args, **kwargs)
+
+
+class PlaceEventUpdate(BaseUpdateView):
+
+ model = PlaceEvent
+ form_class = generate_relation_form(PlaceEvent)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PlaceEventUpdate, self).dispatch(*args, **kwargs)
+
+
+class PlaceEventListView(GenericListView):
+ model = PlaceEvent
+ filter_class = generate_relation_filter(PlaceEvent, PlaceEventRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PlaceEvent)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Orte und Ereignisse"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/place_place_relation_views.py b/apis_core/apis_relations/place_place_relation_views.py
new file mode 100644
index 0000000..013e878
--- /dev/null
+++ b/apis_core/apis_relations/place_place_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import PlacePlaceRelation
+from apis_core.apis_relations.models import PlacePlace
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class PlacePlaceCreate(BaseCreateView):
+
+ model = PlacePlace
+ form_class = generate_relation_form(PlacePlace)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PlacePlaceCreate, self).dispatch(*args, **kwargs)
+
+
+class PlacePlaceUpdate(BaseUpdateView):
+
+ model = PlacePlace
+ form_class = generate_relation_form(PlacePlace)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PlacePlaceUpdate, self).dispatch(*args, **kwargs)
+
+
+class PlacePlaceListView(GenericListView):
+ model = PlacePlace
+ filter_class = generate_relation_filter(PlacePlace, PlacePlaceRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PlacePlace)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Orte und Orte"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/place_work_relation_views.py b/apis_core/apis_relations/place_work_relation_views.py
new file mode 100644
index 0000000..51c02b2
--- /dev/null
+++ b/apis_core/apis_relations/place_work_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import PlaceWorkRelation
+from apis_core.apis_relations.models import PlaceWork
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class PlaceWorkCreate(BaseCreateView):
+
+ model = PlaceWork
+ form_class = generate_relation_form(PlaceWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PlaceWorkCreate, self).dispatch(*args, **kwargs)
+
+
+class PlaceWorkUpdate(BaseUpdateView):
+
+ model = PlaceWork
+ form_class = generate_relation_form(PlaceWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(PlaceWorkUpdate, self).dispatch(*args, **kwargs)
+
+
+class PlaceWorkListView(GenericListView):
+ model = PlaceWork
+ filter_class = generate_relation_filter(PlaceWork, PlaceWorkRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(PlaceWork)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Orte und Werke"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/apis_core/apis_relations/urls.py b/apis_core/apis_relations/urls.py
index af10170..bd45080 100644
--- a/apis_core/apis_relations/urls.py
+++ b/apis_core/apis_relations/urls.py
@@ -4,17 +4,214 @@
from . import person_place_relation_views
from . import person_work_relation_views
from . import person_person_relation_views
-from .views import copy_relation
+from . import person_institution_relation_views
+from . import person_event_relation_views
+from . import place_place_relation_views
+from . import place_event_relation_views
+from . import place_work_relation_views
+from . import institution_institution_relation_views
+from . import institution_place_relation_views
+from . import institution_work_relation_views
+from . import institution_event_relation_views
+from . import event_event_relation_views
+from . import event_work_relation_views
+from . import work_work_relation_views
+from .views import copy_relation, GenericRelationDeleteView
app_name = "apis_relations"
urlpatterns = [
+ path(
+ "delete//",
+ GenericRelationDeleteView.as_view(),
+ name="generic_delete_relation",
+ ),
path(
"copy//",
copy_relation,
name="copy_relation",
),
+ path(
+ "work-work/",
+ work_work_relation_views.WorkWorkListView.as_view(),
+ name="workwork",
+ ),
+ path(
+ "work-work/create/",
+ work_work_relation_views.WorkWorkCreate.as_view(),
+ name="workwork_create",
+ ),
+ path(
+ "work-work/edit/",
+ work_work_relation_views.WorkWorkUpdate.as_view(),
+ name="workwork_edit",
+ ),
+ path(
+ "event-work/",
+ event_work_relation_views.EventWorkListView.as_view(),
+ name="eventwork",
+ ),
+ path(
+ "event-work/create/",
+ event_work_relation_views.EventWorkCreate.as_view(),
+ name="eventwork_create",
+ ),
+ path(
+ "event-work/edit/",
+ event_work_relation_views.EventWorkUpdate.as_view(),
+ name="eventwork_edit",
+ ),
+ path(
+ "event-event/",
+ event_event_relation_views.EventEventListView.as_view(),
+ name="eventevent",
+ ),
+ path(
+ "event-event/create/",
+ event_event_relation_views.EventEventCreate.as_view(),
+ name="eventevent_create",
+ ),
+ path(
+ "event-event/edit/",
+ event_event_relation_views.EventEventUpdate.as_view(),
+ name="eventevent_edit",
+ ),
+ path(
+ "institution-event/",
+ institution_event_relation_views.InstitutionEventListView.as_view(),
+ name="institutionevent",
+ ),
+ path(
+ "institution-event/create/",
+ institution_event_relation_views.InstitutionEventCreate.as_view(),
+ name="institutionevent_create",
+ ),
+ path(
+ "institution-event/edit/",
+ institution_event_relation_views.InstitutionEventUpdate.as_view(),
+ name="institutionevent_edit",
+ ),
+ path(
+ "institution-work/",
+ institution_work_relation_views.InstitutionWorkListView.as_view(),
+ name="institutionwork",
+ ),
+ path(
+ "institution-work/create/",
+ institution_work_relation_views.InstitutionWorkCreate.as_view(),
+ name="institutionwork_create",
+ ),
+ path(
+ "institution-work/edit/",
+ institution_work_relation_views.InstitutionWorkUpdate.as_view(),
+ name="institutionwork_edit",
+ ),
+ path(
+ "institution-place/",
+ institution_place_relation_views.InstitutionPlaceListView.as_view(),
+ name="institutionplace",
+ ),
+ path(
+ "institution-place/create/",
+ institution_place_relation_views.InstitutionPlaceCreate.as_view(),
+ name="institutionplace_create",
+ ),
+ path(
+ "institution-place/edit/",
+ institution_place_relation_views.InstitutionPlaceUpdate.as_view(),
+ name="institutionplace_edit",
+ ),
+ path(
+ "institution-institution/",
+ institution_institution_relation_views.InstitutionInstitutionListView.as_view(),
+ name="institutioninstitution",
+ ),
+ path(
+ "institution-institution/create/",
+ institution_institution_relation_views.InstitutionInstitutionCreate.as_view(),
+ name="institutioninstitution_create",
+ ),
+ path(
+ "institution-institution/edit/",
+ institution_institution_relation_views.InstitutionInstitutionUpdate.as_view(),
+ name="institutioninstitution_edit",
+ ),
+ path(
+ "place-work/",
+ place_work_relation_views.PlaceWorkListView.as_view(),
+ name="placework",
+ ),
+ path(
+ "place-work/create/",
+ place_work_relation_views.PlaceWorkCreate.as_view(),
+ name="placework_create",
+ ),
+ path(
+ "place-work/edit/",
+ place_work_relation_views.PlaceWorkUpdate.as_view(),
+ name="placework_edit",
+ ),
+ path(
+ "place-event/",
+ place_event_relation_views.PlaceEventListView.as_view(),
+ name="placeevent",
+ ),
+ path(
+ "place-event/create/",
+ place_event_relation_views.PlaceEventCreate.as_view(),
+ name="placeevent_create",
+ ),
+ path(
+ "place-event/edit/",
+ place_event_relation_views.PlaceEventUpdate.as_view(),
+ name="placeevent_edit",
+ ),
+ path(
+ "place_place/",
+ place_place_relation_views.PlacePlaceListView.as_view(),
+ name="placeplace",
+ ),
+ path(
+ "place_place/create/",
+ place_place_relation_views.PlacePlaceCreate.as_view(),
+ name="placeplace_create",
+ ),
+ path(
+ "place_place/edit/",
+ place_place_relation_views.PlacePlaceUpdate.as_view(),
+ name="placeplace_edit",
+ ),
+ path(
+ "person-event/",
+ person_event_relation_views.PersonEventListView.as_view(),
+ name="personevent",
+ ),
+ path(
+ "person-event/create/",
+ person_event_relation_views.PersonEventCreate.as_view(),
+ name="personevent_create",
+ ),
+ path(
+ "person-event/edit/",
+ person_event_relation_views.PersonEventUpdate.as_view(),
+ name="personevent_edit",
+ ),
+ path(
+ "person-institution/",
+ person_institution_relation_views.PersonInstitutionListView.as_view(),
+ name="personinstitution",
+ ),
+ path(
+ "person-institution/create/",
+ person_institution_relation_views.PersonInstitutionCreate.as_view(),
+ name="personinstitution_create",
+ ),
+ path(
+ "person-institution/edit/",
+ person_institution_relation_views.PersonInstitutionUpdate.as_view(),
+ name="personinstitution_edit",
+ ),
path(
"person-place/",
person_place_relation_views.PersonPlaceListView.as_view(),
@@ -35,11 +232,31 @@
person_work_relation_views.PersonWorkListView.as_view(),
name="personwork",
),
+ path(
+ "person-work/create/",
+ person_work_relation_views.PersonWorkCreate.as_view(),
+ name="personwork_create",
+ ),
+ path(
+ "person-work/edit/",
+ person_work_relation_views.PersonWorkUpdate.as_view(),
+ name="personwork_edit",
+ ),
path(
"person-person/",
person_person_relation_views.PersonPersonListView.as_view(),
name="personperson",
),
+ path(
+ "person-person/create/",
+ person_person_relation_views.PersonPersonCreate.as_view(),
+ name="personperson_create",
+ ),
+ path(
+ "person-person/edit/",
+ person_person_relation_views.PersonPersonUpdate.as_view(),
+ name="personperson_edit",
+ ),
path(
"delete//",
views.delete_relation_view,
diff --git a/apis_core/apis_relations/utils.py b/apis_core/apis_relations/utils.py
new file mode 100644
index 0000000..abd5898
--- /dev/null
+++ b/apis_core/apis_relations/utils.py
@@ -0,0 +1,241 @@
+from django import forms
+from django_filters import FilterSet, ModelMultipleChoiceFilter, RangeFilter
+from django.urls import reverse_lazy
+
+from crispy_forms.helper import FormHelper
+from crispy_forms.layout import Layout, Submit
+from crispy_bootstrap5.bootstrap5 import BS5Accordion
+from crispy_forms.bootstrap import AccordionGroup
+
+from dal import autocomplete
+
+import django_tables2 as tables
+
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+
+
+def generate_relation_table(MyModelClass):
+ ClassA = MyModelClass.get_related_entity_classa()
+ ClassB = MyModelClass.get_related_entity_classb()
+ class_a_name = ClassA._meta.verbose_name
+ class_b_name = ClassB._meta.verbose_name
+ source_field = MyModelClass.get_related_entity_field_namea()
+ target_field = MyModelClass.get_related_entity_field_nameb()
+
+ class MyTable(tables.Table):
+ source = tables.TemplateColumn(
+ """
+
+ {{ record.get_related_entity_instancea }}
+
+ """,
+ accessor=source_field,
+ verbose_name=class_a_name,
+ )
+ target = tables.TemplateColumn(
+ """
+
+ {{ record.get_related_entity_instanceb }}
+
+ """,
+ accessor=target_field,
+ verbose_name=class_b_name,
+ )
+ relation_type = tables.TemplateColumn(
+ "{{ record.relation_type }}", verbose_name="Art der Beziehung"
+ )
+ start_date_written = tables.TemplateColumn(
+ "{% if record.start_date_written %} {{ record.start_date_written }} {% endif %}",
+ verbose_name="Start",
+ )
+ end_date_written = tables.TemplateColumn(
+ "{% if record.end_date_written %} {{ record.end_date_written }} {% endif %}",
+ verbose_name="End",
+ )
+ crud = tables.TemplateColumn(
+ """
+
+
+ Verbindung bearbeiten
+
+
+
+
+
+
+
+
+ """,
+ verbose_name="Ändern, Kopieren oder Löschen",
+ orderable=False,
+ exclude_from_export=True,
+ )
+
+ class Meta:
+ model = MyModelClass
+ sequence = (
+ "id",
+ "source",
+ "relation_type",
+ "target",
+ "start_date_written",
+ "end_date_written",
+ )
+
+ return MyTable
+
+
+def generate_relation_filter(MyModelClass, RelationTypeClass):
+ ClassA = MyModelClass.get_related_entity_classa()
+ ClassB = MyModelClass.get_related_entity_classb()
+ class_a_name = ClassA.__name__
+ class_b_name = ClassB.__name__
+ class_a_verbose_name = ClassA._meta.verbose_name_plural
+ class_b_verbose_name = ClassB._meta.verbose_name_plural
+ source_field = MyModelClass.get_related_entity_field_namea()
+ target_field = MyModelClass.get_related_entity_field_nameb()
+
+ class MyRelationsListFilter(FilterSet):
+ source = ModelMultipleChoiceFilter(
+ field_name=source_field,
+ queryset=ClassA.objects.all(),
+ help_text=f"Wähle eine oder mehrere {class_a_verbose_name}",
+ label=class_a_verbose_name,
+ widget=autocomplete.Select2Multiple(
+ url=reverse_lazy(
+ "apis:apis_entities:generic_entities_autocomplete",
+ kwargs={"entity": class_a_name.lower()},
+ ),
+ attrs={"data-html": True},
+ ),
+ )
+ target = ModelMultipleChoiceFilter(
+ field_name=target_field,
+ queryset=ClassB.objects.all(),
+ help_text=f"Wähle einen oder mehrere {class_b_verbose_name}",
+ label=class_b_verbose_name,
+ widget=autocomplete.Select2Multiple(
+ url=reverse_lazy(
+ "apis:apis_entities:generic_entities_autocomplete",
+ kwargs={"entity": class_b_name.lower()},
+ ),
+ attrs={"data-html": True},
+ ),
+ )
+ relation_type = ModelMultipleChoiceFilter(
+ queryset=RelationTypeClass.objects.all().order_by("name"),
+ label="Art der Beziehung",
+ help_text="Mehrfachauswahl möglich",
+ )
+ start_date__year = RangeFilter(
+ label="Anfang (Jahr)",
+ )
+ end_date__year = RangeFilter(
+ label="Ende (Jahr)",
+ )
+
+ class Meta:
+ model = MyModelClass
+ fields = [
+ source_field,
+ target_field,
+ "relation_type",
+ "start_date__year",
+ "end_date__year",
+ ]
+
+ return MyRelationsListFilter
+
+
+def generate_relation_filter_formhelper():
+
+ class MyRelationsFilterFormHelper(FormHelper):
+ def __init__(self, *args, **kwargs):
+ super(MyRelationsFilterFormHelper, self).__init__(*args, **kwargs)
+ self.helper = FormHelper()
+ self.form_class = "genericFilterForm"
+ self.form_method = "GET"
+ self.form_tag = False
+ self.layout = Layout(
+ "source",
+ "target",
+ "relation_type",
+ "start_date__year",
+ "end_date__year",
+ )
+
+ return MyRelationsFilterFormHelper
+
+
+def generate_relation_form(MyModelClass):
+ ClassA = MyModelClass.get_related_entity_classa()
+ ClassB = MyModelClass.get_related_entity_classb()
+ class_a_name = ClassA.__name__
+ class_b_name = ClassB.__name__
+
+ class MyForm(forms.ModelForm):
+
+ class Meta:
+ model = MyModelClass
+ exclude = FIELDS_TO_EXCLUDE + [
+ "collection",
+ ]
+ widgets = {
+ MyModelClass.get_related_entity_field_namea(): autocomplete.ModelSelect2(
+ url=reverse_lazy(
+ "apis:apis_entities:generic_entities_autocomplete",
+ kwargs={"entity": f"{class_a_name.lower()}"},
+ ),
+ attrs={"data-html": True},
+ ),
+ MyModelClass.get_related_entity_field_nameb(): autocomplete.ModelSelect2(
+ url=reverse_lazy(
+ "apis:apis_entities:generic_entities_autocomplete",
+ kwargs={"entity": f"{class_b_name.lower()}"},
+ ),
+ attrs={"data-html": True},
+ ),
+ }
+
+ def __init__(self, *args, **kwargs):
+ super(MyForm, self).__init__(*args, **kwargs)
+ self.helper = FormHelper()
+ self.helper.form_tag = True
+ self.current_model = self._meta.model
+ self.fields[
+ self.current_model.get_related_entity_field_namea()
+ ].required = True
+ self.fields["relation_type"].required = True
+ self.fields[
+ self.current_model.get_related_entity_field_nameb()
+ ].required = True
+ self.helper.form_class = "form-horizontal"
+ self.helper.label_class = "col-md-3"
+ self.helper.field_class = "col-md-9"
+ self.helper.add_input(
+ Submit("submit", "save"),
+ )
+ self.helper.layout = Layout(
+ BS5Accordion(
+ AccordionGroup(
+ "Sehr wichtige Felder",
+ self.current_model.get_related_entity_field_namea(),
+ "relation_type",
+ self.current_model.get_related_entity_field_nameb(),
+ "start_date_written",
+ "end_date_written",
+ ),
+ AccordionGroup(
+ "Notizen und Referenzen",
+ "notes",
+ "references",
+ ),
+ AccordionGroup(
+ "Datumsfelder",
+ "start_date",
+ "end_date",
+ ),
+ )
+ )
+
+ return MyForm
diff --git a/apis_core/apis_relations/views.py b/apis_core/apis_relations/views.py
index 5ae38c8..1802b53 100644
--- a/apis_core/apis_relations/views.py
+++ b/apis_core/apis_relations/views.py
@@ -2,11 +2,14 @@
import re
from django.apps import apps
+
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect
from django.template import loader
+from django.views.generic.edit import DeleteView
+
from apis_core.apis_entities.models import (
AbstractEntity,
@@ -53,6 +56,25 @@ def copy_relation(request, relation_class, pk):
return redirect(original_object.get_edit_url())
+class GenericRelationDeleteView(DeleteView):
+ template_name = "apis_entities/confirm_delete.html"
+
+ def get_model(self):
+ model_name = self.kwargs.get("relation_class")
+ model = apps.get_model(app_label="apis_relations", model_name=model_name)
+ return model
+
+ def get_object(self):
+ model = self.get_model()
+ obj = get_object_or_404(model, pk=self.kwargs["pk"])
+ return obj
+
+ def get_success_url(self):
+ obj = self.get_object()
+ url = obj.get_listview_url()
+ return url
+
+
def turn_form_modules_into_dict(form_module_list):
"""
Since form classes are loaded dynamically from the respective modules and it's settings-dependent which modules
diff --git a/apis_core/apis_relations/work_work_relation_views.py b/apis_core/apis_relations/work_work_relation_views.py
new file mode 100644
index 0000000..40dd5b8
--- /dev/null
+++ b/apis_core/apis_relations/work_work_relation_views.py
@@ -0,0 +1,59 @@
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+
+from browsing.browsing_utils import GenericListView, BaseCreateView, BaseUpdateView
+
+from apis_core.apis_vocabularies.models import WorkWorkRelation
+from apis_core.apis_relations.models import WorkWork
+from apis_core.apis_relations.config import FIELDS_TO_EXCLUDE
+from apis_core.apis_relations.utils import (
+ generate_relation_form,
+ generate_relation_filter_formhelper,
+ generate_relation_filter,
+ generate_relation_table,
+)
+
+
+class WorkWorkCreate(BaseCreateView):
+
+ model = WorkWork
+ form_class = generate_relation_form(WorkWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(WorkWorkCreate, self).dispatch(*args, **kwargs)
+
+
+class WorkWorkUpdate(BaseUpdateView):
+
+ model = WorkWork
+ form_class = generate_relation_form(WorkWork)
+
+ def get_success_url(self):
+ return self.object.get_object_list_view()
+
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(WorkWorkUpdate, self).dispatch(*args, **kwargs)
+
+
+class WorkWorkListView(GenericListView):
+ model = WorkWork
+ filter_class = generate_relation_filter(WorkWork, WorkWorkRelation)
+ formhelper_class = generate_relation_filter_formhelper()
+ table_class = generate_relation_table(WorkWork)
+ init_columns = [
+ "start_date_written",
+ "end_date_written",
+ "source",
+ "relation_type",
+ "target",
+ "crud",
+ ]
+ verbose_name = "Werke und Werke"
+ exclude_columns = FIELDS_TO_EXCLUDE
+ enable_merge = False
+ template_name = "apis_relations/list_view.html"
diff --git a/notebooks/issue__222_schubert-persons.ipynb b/notebooks/issue__222_schubert-persons.ipynb
new file mode 100644
index 0000000..bcdfd35
--- /dev/null
+++ b/notebooks/issue__222_schubert-persons.ipynb
@@ -0,0 +1,128 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "996db3a8-afd9-478d-9786-dd0275216e9e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# run against production 2024-10-10\n",
+ "from acdh_tei_pyutils.tei import TeiReader\n",
+ "from normdata.utils import import_from_normdata\n",
+ "from tqdm import tqdm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "36b53039-f80b-4b29-b6f7-029e6f0da76d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "doc = TeiReader(\"https://schubert-digital.at/export/personen.xml\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2598232e-8193-4fa5-8159-918d4ca6e76c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nsmap = {\"tei\": \"http://www.music-encoding.org/ns/mei\"}\n",
+ "col, _ = Collection.objects.get_or_create(name=\"Schubert Digital\")\n",
+ "domain = \"schubert-digital\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "080d64de-e40b-4aa3-94a0-adcc59c2c508",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "broken_gnd = []\n",
+ "pmb_uris = []\n",
+ "for x in tqdm(doc.tree.xpath(\".//tei:persName[@xml:id]\", namespaces=nsmap)):\n",
+ " try:\n",
+ " gnd = x.xpath(\".//tei:identifier[@auth='GND']\", namespaces=nsmap)[0].text\n",
+ " except:\n",
+ " gnd = False\n",
+ " continue\n",
+ " if gnd:\n",
+ " xml_id = x.xpath(\".//tei:identifier[@label='Schubert-Personenregister-ID']/text()\", namespaces=nsmap)[0]\n",
+ " domain_uri = f\"https://schubert-digital.at/{xml_id}.html\"\n",
+ " gnd_uri = f\"https://d-nb.info/gnd/{gnd}\"\n",
+ " entity = import_from_normdata(gnd_uri, \"person\")\n",
+ " if entity:\n",
+ " pmb_uri, _ = Uri.objects.get_or_create(uri=domain_uri, domain=domain)\n",
+ " pmb_uri.entity = entity\n",
+ " pmb_uri.save()\n",
+ " entity.collection.add(col)\n",
+ " pmb_uris.append([xml_id, entity.id])\n",
+ " else:\n",
+ " broken_gnd.append(gnd_uri)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69207701-41c4-4151-b36a-037613baa634",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1924a736-e302-4a29-83f2-9fa1704bbbe0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame(pmb_uris)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7845bd29-14c4-45f3-a689-bae05829ed45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.to_csv('schubert_pmb.csv', index=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ba9f5899-a9c2-474a-9d12-5977d5c698c6",
+ "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
+}
diff --git a/notebooks/issue__223_brahms-persons .ipynb b/notebooks/issue__223_brahms-persons .ipynb
new file mode 100644
index 0000000..2053f14
--- /dev/null
+++ b/notebooks/issue__223_brahms-persons .ipynb
@@ -0,0 +1,119 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "996db3a8-afd9-478d-9786-dd0275216e9e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# run against prodcution 2024-10-10\n",
+ "import pandas as pd\n",
+ "from acdh_tei_pyutils.tei import TeiReader\n",
+ "from normdata.utils import import_from_normdata\n",
+ "from tqdm import tqdm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "36b53039-f80b-4b29-b6f7-029e6f0da76d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "doc = TeiReader(\"https://brahms-online.oeaw.ac.at/export/personen.xml\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2598232e-8193-4fa5-8159-918d4ca6e76c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nsmap = {\"tei\": \"http://www.music-encoding.org/ns/mei\"}\n",
+ "col, _ = Collection.objects.get_or_create(name=\"Brahms Online\")\n",
+ "domain = \"brahms-online\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "080d64de-e40b-4aa3-94a0-adcc59c2c508",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "broken_gnd = []\n",
+ "pmb_uris = []\n",
+ "for x in tqdm(doc.tree.xpath(\".//tei:persName[@xml:id]\", namespaces=nsmap)):\n",
+ " try:\n",
+ " gnd = x.xpath(\".//tei:identifier[@auth='GND']\", namespaces=nsmap)[0].text\n",
+ " except:\n",
+ " gnd = False\n",
+ " continue\n",
+ " if gnd:\n",
+ " xml_id = x.xpath(\".//tei:identifier[@label='Register-ID']/text()\", namespaces=nsmap)[0]\n",
+ " domain_uri = f\"https://brahms-online.oeaw.ac.at/personenregister-id-{xml_id}.html\"\n",
+ " gnd_uri = f\"https://d-nb.info/gnd/{gnd}\"\n",
+ " entity = import_from_normdata(gnd_uri, \"person\")\n",
+ " if entity:\n",
+ " pmb_uri, _ = Uri.objects.get_or_create(uri=domain_uri, domain=domain)\n",
+ " pmb_uri.entity = entity\n",
+ " pmb_uri.save()\n",
+ " entity.collection.add(col)\n",
+ " pmb_uris.append([xml_id, entity.id])\n",
+ " else:\n",
+ " broken_gnd.append(gnd_uri)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1924a736-e302-4a29-83f2-9fa1704bbbe0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame(pmb_uris)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7845bd29-14c4-45f3-a689-bae05829ed45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.to_csv('brahms_pmb.csv', index=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ba9f5899-a9c2-474a-9d12-5977d5c698c6",
+ "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
+}
diff --git a/templates/partials/navbar.html b/templates/partials/navbar.html
index dc534a5..9913826 100644
--- a/templates/partials/navbar.html
+++ b/templates/partials/navbar.html
@@ -76,6 +76,13 @@
Relationen
{% if user.is_authenticated %}