Coverage for apis_core/relations/templatetags/relations.py: 43%
51 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-06-25 10:00 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-06-25 10:00 +0000
1from django import template
2from django.contrib.contenttypes.models import ContentType
3from django.db.models import Case, Q, Value, When
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
10register = template.Library()
13@register.simple_tag
14def possible_relation_types_from(obj) -> list[ContentType]:
15 return relation_content_types(any_model=type(obj))
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 )
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()
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
59@register.simple_tag(takes_context=True)
60def relations_list_table(context, relations, suffix=None):
61 suffixes = ["RelationsTable"]
62 if suffix:
63 suffixes.insert(0, f"{suffix}RelationsTable")
64 table_modules = ()
65 for suffix in suffixes:
66 table_modules += module_paths(
67 type(context["object"]), path="tables", suffix=suffix
68 )
69 table_class = first_member_match(table_modules, RelationsListTable)
70 return table_class(relations, request=context["request"])
73@register.simple_tag
74def get_relation_content_types():
75 return relation_content_types()
78@register.simple_tag
79def get_relation_between_content_types(source: ContentType, target: ContentType):
80 return relation_content_types(
81 combination=(source.model_class(), target.model_class())
82 )
85@register.simple_tag(takes_context=True)
86def relations_instances_from_relation_types(context, relation_types):
87 relations = []
88 for relation_type in relation_types:
89 relations.extend(relations_from(context["object"], relation_type))
90 return relations