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( - """ - - - - - - - - """, - 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( + """ + + + + + + + + + + """, + 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 %}