Coverage for apis_core/apis_entities/models.py: 60%
63 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-02-19 16:54 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-02-19 16:54 +0000
1import functools
2import re
4from django.conf import settings
5from django.contrib.contenttypes.models import ContentType
6from django.db.models.signals import post_save
7from django.dispatch import receiver
8from django.urls import NoReverseMatch, reverse
10from apis_core.apis_metainfo.models import RootObject, Uri
12NEXT_PREV = getattr(settings, "APIS_NEXT_PREV", True)
15class AbstractEntity(RootObject):
16 """
17 Abstract super class which encapsulates common logic between the
18 different entity kinds and provides various methods relating to either
19 all or one specific entity kind.
21 Most of the class methods are designed to be used in the subclass as they
22 are considering contexts which depend on the subclass entity type.
23 So they are to be understood in that dynamic context.
24 """
26 class Meta:
27 abstract = True
29 @classmethod
30 def get_or_create_uri(cls, uri):
31 uri = str(uri)
32 try:
33 if re.match(r"^[0-9]*$", uri):
34 p = cls.objects.get(pk=uri)
35 else:
36 p = cls.objects.get(uri__uri=uri)
37 return p
38 except Exception as e:
39 print("Found no object corresponding to given uri." + e)
40 return False
42 # TODO
43 @classmethod
44 def get_entity_list_filter(cls):
45 return None
47 @functools.cached_property
48 def get_prev_id(self):
49 if NEXT_PREV:
50 prev_instance = (
51 type(self)
52 .objects.filter(id__lt=self.id)
53 .order_by("-id")
54 .only("id")
55 .first()
56 )
57 if prev_instance is not None:
58 return prev_instance.id
59 return False
61 @functools.cached_property
62 def get_next_id(self):
63 if NEXT_PREV:
64 next_instance = (
65 type(self)
66 .objects.filter(id__gt=self.id)
67 .order_by("id")
68 .only("id")
69 .first()
70 )
71 if next_instance is not None:
72 return next_instance.id
73 return False
75 def get_duplicate_url(self):
76 entity = self.__class__.__name__.lower()
77 return reverse(
78 "apis_core:apis_entities:generic_entities_duplicate_view",
79 kwargs={"contenttype": entity, "pk": self.id},
80 )
82 def merge_start_date_written(self, other):
83 self.start_date_written = self.start_date_written or other.start_date_written
85 def merge_end_date_written(self, other):
86 self.end_date_written = self.end_date_written or other.end_date_written
89@receiver(post_save, dispatch_uid="create_default_uri")
90def create_default_uri(sender, instance, created, raw, using, update_fields, **kwargs):
91 # disable the handler during fixture loading
92 if raw:
93 return
94 create_default_uri = getattr(settings, "CREATE_DEFAULT_URI", True)
95 skip_default_uri = getattr(instance, "skip_default_uri", False)
96 if create_default_uri and not skip_default_uri:
97 if isinstance(instance, AbstractEntity) and created:
98 base = getattr(settings, "APIS_BASE_URI", "https://example.org").strip("/")
99 try:
100 route = reverse("GetEntityGenericRoot", kwargs={"pk": instance.pk})
101 except NoReverseMatch:
102 route = reverse(
103 "apis_core:GetEntityGeneric", kwargs={"pk": instance.pk}
104 )
105 uri = f"{base}{route}"
106 content_type = ContentType.objects.get_for_model(instance)
107 Uri.objects.create(
108 uri=uri,
109 content_type=content_type,
110 object_id=instance.id,
111 )