Source code for apis_core.apis_relations.forms

import copy

from crispy_forms.helper import FormHelper
from dal import autocomplete
from django import forms
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.urls import reverse
from django_tables2 import RequestConfig

from apis_core.apis_entities.autocomplete3 import (
    PropertyAutocomplete,
)
from apis_core.apis_entities.fields import ListSelect2
from apis_core.apis_entities.utils import get_entity_classes
from apis_core.apis_metainfo.models import Uri
from apis_core.apis_relations.models import TempTriple
from apis_core.utils.settings import get_entity_settings_by_modelname

from .tables import get_generic_triple_table


[docs] class GenericTripleForm(forms.ModelForm): # TODO RDF : Add Notes and references
[docs] class Meta: model = TempTriple fields = [ "subj", "obj", "prop", "start_date_written", "end_date_written", "notes", ] widgets = { "subj": forms.HiddenInput(), "obj": forms.HiddenInput(), "prop": forms.HiddenInput(), }
def __init__(self, entity_type_self_str, entity_type_other_str): super().__init__() self.helper = FormHelper() self.helper.form_tag = False attrs = { "data-placeholder": "Type to get suggestions", "data-minimum-input-length": getattr(settings, "APIS_MIN_CHAR", 3), "data-html": True, "style": "width: 100%", } help_text_other_entity = ( "Search and select or use an URL from a reference resource" ) attrs_target = copy.deepcopy(attrs) attrs_target["data-tags"] = "1" contenttypes = [ ContentType.objects.get_for_model(model) for model in get_entity_classes() ] ct = next( filter(lambda x: x.model == entity_type_other_str.lower(), contenttypes) ) url = reverse("apis_core:generic:autocomplete", args=[ct]) + "?create=True" self.fields["other_entity"] = autocomplete.Select2ListCreateChoiceField( label="entity", widget=ListSelect2( url=url, attrs=attrs_target, ), help_text=help_text_other_entity, ) # This assert only serves as a linking for us devs, to make explicit what internal object the class # Select2ListCreateChoiceField object afterwards uses. assert PropertyAutocomplete self.fields["property"] = autocomplete.Select2ListCreateChoiceField( label="property", widget=ListSelect2( url=reverse( "apis_core:apis_relations:generic_property_autocomplete", kwargs={ "entity_self": entity_type_self_str, "entity_other": entity_type_other_str, }, ), attrs=attrs_target, ), ) self.helper.include_media = False
[docs] def load_subj_obj_prop( self, entity_instance_self, entity_instance_other, property_instance, property_direction, ): # the more important function here when writing data from an user input via an ajax call into this form. # Because here the direction of the property is respected. Hence the subject and object position of the # triple and the property name_forward or name_reverse are loaded correctly here. if property_direction == PropertyAutocomplete.SELF_SUBJ_OTHER_OBJ_STR: triple_subj = entity_instance_self triple_obj = entity_instance_other property_direction_name = property_instance.name_forward elif property_direction == PropertyAutocomplete.SELF_OBJ_OTHER_SUBJ_STR: triple_subj = entity_instance_other triple_obj = entity_instance_self property_direction_name = property_instance.name_reverse else: raise Exception("No valid property direction given.") self.fields["subj"].initial = triple_subj self.fields["obj"].initial = triple_obj self.fields["prop"].initial = property_instance property_initial_value = ( f"id:{property_instance.pk}__direction:{property_direction}", property_direction_name, ) self.fields["property"].initial = property_initial_value self.fields["property"].choices = [property_initial_value] other_entity_initial_value = ( str( Uri.objects.filter( root_object=entity_instance_other, ).first() ), f"<span ><small>db</small> {str(entity_instance_other)}</span>", ) self.fields["other_entity"].initial = other_entity_initial_value self.fields["other_entity"].choices = [other_entity_initial_value]
[docs] def load_remaining_data_from_triple(self, triple): # Most data is loaded via the set_subj_obj function. # Here, load the rest from a pre-existing triple. # # This function is both used in get_form_ajax and save_form_ajax, # hence it's not feasible to assume existing user input as done # in 'load_remaining_data_from_input' self.fields["start_date_written"].initial = triple.start_date_written self.fields["end_date_written"].initial = triple.end_date_written self.fields["notes"].initial = triple.notes self.instance = triple
[docs] def load_remaining_data_from_input( self, start_date_written, end_date_written, ): # Most data is loaded via the set_subj_obj function. # Here, load the rest from the user input via the ajax post self.fields["start_date_written"].initial = start_date_written self.fields["end_date_written"].initial = end_date_written
[docs] def save(self): if self.instance.pk is None: self.instance = TempTriple.objects.create( subj=self.fields["subj"].initial, obj=self.fields["obj"].initial, prop=self.fields["prop"].initial, ) else: self.instance.subj = self.fields["subj"].initial self.instance.obj = self.fields["obj"].initial self.instance.prop = self.fields["prop"].initial self.instance.start_date_written = self.fields["start_date_written"].initial self.instance.end_date_written = self.fields["end_date_written"].initial self.instance.notes = self.fields["notes"].initial self.instance.save() return self.instance
[docs] def get_text_id(self): """ Function to retrieve the highlighted text. :return: ID of text that was highlighted """ return self.cleaned_data["HL_text_id"][5:]
[docs] def get_html_table(self, entity_instance_self, entity_instance_other, request): table_class = get_generic_triple_table( other_entity_class_name=entity_instance_other.__class__.__name__.lower(), entity_pk_self=entity_instance_self.pk, detail=False, ) table_object = table_class( data=TempTriple.objects.filter( ( Q(subj__self_contenttype=entity_instance_other.self_contenttype) & Q(obj=entity_instance_self) ) | ( Q(obj__self_contenttype=entity_instance_other.self_contenttype) & Q(subj=entity_instance_self) ) ), prefix=entity_instance_other.__class__.__name__, request=request, ) entity_settings = get_entity_settings_by_modelname( entity_instance_self.__class__.__name__ ) per_page = entity_settings.get("relations_per_page", 10) RequestConfig(request, paginate={"per_page": per_page}).configure(table_object) return table_object