Coverage for apis_core/relations/views.py: 38%

58 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-06-25 10:00 +0000

1from django.contrib.contenttypes.models import ContentType 

2from django.urls import reverse 

3from django.utils.http import urlencode 

4from django.views.generic.base import TemplateView 

5from django.views.generic.detail import BaseDetailView 

6 

7from apis_core.generic.helpers import split_and_strip_parameter, string_to_bool 

8from apis_core.generic.templatetags.generic import content_types_by_natural_keys 

9from apis_core.generic.views import Create, GenericModelMixin 

10from apis_core.relations.templatetags.relations import ( 

11 possible_relation_types_from, 

12 relations_from, 

13) 

14 

15 

16class CreateRelation(Create): 

17 def get_form_kwargs(self, *args, **kwargs) -> dict: 

18 kwargs = super().get_form_kwargs(*args, **kwargs) 

19 kwargs["initial"]["obj_content_type"] = self.request.GET.get("obj_content_type") 

20 kwargs["initial"]["obj_object_id"] = self.request.GET.get("obj_object_id") 

21 kwargs["initial"]["subj_content_type"] = self.request.GET.get( 

22 "subj_content_type" 

23 ) 

24 kwargs["initial"]["subj_object_id"] = self.request.GET.get("subj_object_id") 

25 return kwargs 

26 

27 

28class RelationParamsMixin: 

29 def setup(self, *args, **kwargs) -> None: 

30 super().setup(*args, **kwargs) 

31 self.params = self.request.GET.dict() 

32 self.params["reverse"] = string_to_bool(self.params.get("reverse", "false")) 

33 self.params["relation_types"] = split_and_strip_parameter( 

34 self.request.GET.getlist("relation_types") 

35 ) 

36 

37 

38class CreateRelationForm(RelationParamsMixin, CreateRelation): 

39 template_name = "relations/create_relation_form.html" 

40 

41 def get(self, *args, **kwargs): 

42 resp = super().get(*args, **kwargs) 

43 content_type = ContentType.objects.get_for_model(self.model) 

44 resp["HX-Trigger-After-Settle"] = ( 

45 '{"reinit_select2": "relation_' + content_type.model + '_form"}' 

46 ) 

47 return resp 

48 

49 def get_form_kwargs(self, *args, **kwargs) -> dict: 

50 kwargs = super().get_form_kwargs(*args, **kwargs) 

51 kwargs["params"] = self.params 

52 content_type = ContentType.objects.get_for_model(self.model) 

53 kwargs["params"]["hx_post_route"] = reverse( 

54 "apis_core:relations:create_relation_form", args=[content_type] 

55 ) 

56 return kwargs 

57 

58 def get_success_url(self) -> str: 

59 obj = self.object.obj if self.params["reverse"] else self.object.subj 

60 args = [obj.content_type, obj.id] 

61 params = { 

62 k: self.params[k] for k in ["relation_types", "replace_id", "table_suffix"] 

63 } 

64 params = "?" + urlencode(params, doseq=True) 

65 return reverse("apis_core:relations:list_relations", args=args) + params 

66 

67 

68class ListRelations( 

69 RelationParamsMixin, GenericModelMixin, BaseDetailView, TemplateView 

70): 

71 template_name = "relations/partials/list_relations.html" 

72 

73 def get_context_data(self, *args, **kwargs) -> dict: 

74 ctx = super().get_context_data(*args, **kwargs) 

75 ctx["relations"] = [] 

76 

77 relation_types = content_types_by_natural_keys( 

78 tuple(self.params["relation_types"]) 

79 ) 

80 if not relation_types: 

81 relation_types = possible_relation_types_from(self.object) 

82 for relation_type in relation_types: 

83 ctx["relations"].extend(relations_from(self.object, relation_type)) 

84 

85 ctx.update(self.params) 

86 

87 return ctx 

88 

89 def get(self, *args, **kwargs): 

90 resp = super().get(*args, **kwargs) 

91 resp["HX-Trigger"] = "dismissModal" 

92 return resp