Coverage for apis_core/relations/templatetags/relations.py: 44%

41 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-16 07:42 +0000

1from django import template 

2from django.contrib.contenttypes.models import ContentType 

3from django.db.models import Case, Q, Value, When 

4 

5from apis_core.generic.helpers import first_member_match, module_paths 

6from apis_core.relations.models import Relation 

7from apis_core.relations.tables import RelationsListTable 

8from apis_core.relations.utils import relation_content_types, relation_match_target 

9 

10register = template.Library() 

11 

12 

13@register.simple_tag 

14def possible_relation_types_from(obj) -> list[ContentType]: 

15 return relation_content_types(any_model=type(obj)) 

16 

17 

18@register.simple_tag 

19def get_relation_targets_from(obj) -> list[ContentType]: 

20 relations = relation_content_types(any_model=type(obj)) 

21 types = set() 

22 for model in [relation.model_class() for relation in relations]: 

23 if type(obj) in model.obj_list(): 

24 types.update(model.subj_list()) 

25 if type(obj) in model.subj_list(): 

26 types.update(model.obj_list()) 

27 return sorted( 

28 list(map(ContentType.objects.get_for_model, types)), key=lambda x: x.name 

29 ) 

30 

31 

32@register.simple_tag 

33def relations_from(from_obj, relation_type: ContentType = None): 

34 from_content_type = ContentType.objects.get_for_model(from_obj) 

35 relation = Relation 

36 if relation_type is not None: 

37 relation = relation_type.model_class() 

38 

39 relations = ( 

40 relation.objects.filter( 

41 Q(subj_content_type=from_content_type, subj_object_id=from_obj.id) 

42 | Q(obj_content_type=from_content_type, obj_object_id=from_obj.id) 

43 ) 

44 .annotate( 

45 forward=Case( 

46 When( 

47 subj_content_type=from_content_type, 

48 subj_object_id=from_obj.id, 

49 then=Value(True), 

50 ), 

51 default=Value(False), 

52 ) 

53 ) 

54 .select_subclasses() 

55 ) 

56 return relations 

57 

58 

59@register.simple_tag(takes_context=True) 

60def relations_list_table(context, relations, target=None): 

61 table_modules = module_paths( 

62 type(context["object"]), 

63 path="tables", 

64 suffix=f"{target.name.capitalize()}RelationsTable", 

65 ) 

66 table_class = first_member_match(table_modules, RelationsListTable) 

67 if target: 

68 relations = [ 

69 relation 

70 for relation in relations 

71 if relation_match_target(relation, target) 

72 ] 

73 return table_class(relations, request=context["request"]) 

74 

75 

76@register.simple_tag 

77def relations_verbose_name_listview_url(): 

78 """ 

79 Return all relations verbose names together with their list uri, sorted in alphabetical order 

80 USED BY: 

81 * `apis_core/relations/templates/base.html` (to extend the default `base.html`) 

82 """ 

83 relation_classes = [relation.model_class() for relation in relation_content_types()] 

84 ret = { 

85 relation._meta.verbose_name: relation.get_listview_url() 

86 for relation in relation_classes 

87 } 

88 return sorted(ret.items())