Coverage for apis_core/collections/models.py: 86%

37 statements  

« prev     ^ index     » next       coverage.py v7.6.8, created at 2024-12-20 09:24 +0000

1from django.contrib.contenttypes.fields import GenericForeignKey 

2from django.contrib.contenttypes.models import ContentType 

3from django.db import models 

4 

5from apis_core.generic.abc import GenericModel 

6 

7 

8class SkosCollectionManager(models.Manager): 

9 def get_by_full_path(self, name: str): 

10 """ 

11 Return a collection specified by its full path, from the root colletion 

12 to the leaf collection, delimited by `|`. I.e. if there is a collection 

13 named `foo` and it has a parent named `bar` and `bar` does not have a 

14 parent, then you can use the string "bar|foo" to get the `foo` collection. 

15 """ 

16 names = name.split("|") 

17 parent = None 

18 while names: 

19 parent = self.get(parent=parent, name=names.pop(0)) 

20 return parent 

21 

22 

23class SkosCollection(GenericModel, models.Model): 

24 """ 

25 SKOS collections are labeled and/or ordered groups of SKOS concepts. 

26 Collections are useful where a group of concepts shares something in common, 

27 and it is convenient to group them under a common label, or 

28 where some concepts can be placed in a meaningful order. 

29 

30 Miles, Alistair, and Sean Bechhofer. "SKOS simple knowledge 

31 organization system reference. W3C recommendation (2009)." 

32 

33 """ 

34 

35 class Meta: 

36 ordering = ["name"] 

37 constraints = [ 

38 models.UniqueConstraint( 

39 fields=( 

40 "name", 

41 "parent", 

42 ), 

43 name="unique_name_parent", 

44 nulls_distinct=False, 

45 violation_error_message="The combination of name and parent collection must be unique", 

46 ), 

47 models.CheckConstraint( 

48 check=~models.Q(name__contains="|"), 

49 name="check_name_pipe", 

50 violation_error_message="The name must not contain the pipe symbol: |", 

51 ), 

52 ] 

53 

54 parent = models.ForeignKey("self", null=True, on_delete=models.CASCADE, blank=True) 

55 name = models.CharField( 

56 max_length=300, 

57 verbose_name="skos:prefLabel", 

58 help_text="Collection label or name", 

59 ) 

60 label_lang = models.CharField( 

61 max_length=3, 

62 blank=True, 

63 default="en", 

64 verbose_name="skos:prefLabel language", 

65 help_text="Language of preferred label given above", 

66 ) 

67 creator = models.TextField( 

68 blank=True, 

69 verbose_name="dc:creator", 

70 help_text="Person or organisation that created this collection" 

71 "If more than one list all using a semicolon ;", 

72 ) 

73 contributor = models.TextField( 

74 blank=True, 

75 verbose_name="dc:contributor", 

76 help_text="Person or organisation that made contributions to the collection" 

77 "If more than one list all using a semicolon ;", 

78 ) 

79 objects = SkosCollectionManager() 

80 

81 def __str__(self): 

82 return self.name 

83 

84 def children(self): 

85 return SkosCollection.objects.filter(parent=self) 

86 

87 def children_tree_as_list(self): 

88 childtrees = [self] 

89 for child in self.children(): 

90 childtrees.extend(child.children_tree_as_list()) 

91 return childtrees 

92 

93 

94class SkosCollectionContentObject(GenericModel, models.Model): 

95 """ 

96 *Throughtable* datamodel to connect collections to arbitrary content 

97 """ 

98 

99 collection = models.ForeignKey(SkosCollection, on_delete=models.CASCADE) 

100 

101 content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) 

102 object_id = models.PositiveIntegerField() 

103 content_object = GenericForeignKey("content_type", "object_id") 

104 

105 def __str__(self): 

106 return f"{self.content_object} -> {self.collection}"