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

1import functools 

2import re 

3 

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 

9 

10from apis_core.apis_metainfo.models import RootObject, Uri 

11 

12NEXT_PREV = getattr(settings, "APIS_NEXT_PREV", True) 

13 

14 

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. 

20 

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 """ 

25 

26 class Meta: 

27 abstract = True 

28 

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 

41 

42 # TODO 

43 @classmethod 

44 def get_entity_list_filter(cls): 

45 return None 

46 

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 

60 

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 

74 

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 ) 

81 

82 def merge_start_date_written(self, other): 

83 self.start_date_written = self.start_date_written or other.start_date_written 

84 

85 def merge_end_date_written(self, other): 

86 self.end_date_written = self.end_date_written or other.end_date_written 

87 

88 

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 )