Coverage for apis_core/generic/tables.py: 89%

53 statements  

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

1import django_tables2 as tables 

2 

3from apis_core.generic.helpers import permission_fullname 

4 

5 

6class CustomTemplateColumn(tables.TemplateColumn): 

7 """ 

8 A custom template column - the `tables.TemplateColumn` class does not allow 

9 to set attributes via class variables. Therefor we use this 

10 CustomTemplateColumn to set some arguments based on class attributes and 

11 override the attributes in child classes. 

12 """ 

13 

14 template_name = None 

15 orderable = None 

16 exclude_from_export = False 

17 verbose_name = None 

18 

19 def __init__(self, *args, **kwargs): 

20 super().__init__( 

21 template_name=self.template_name, 

22 orderable=self.orderable, 

23 exclude_from_export=self.exclude_from_export, 

24 verbose_name=self.verbose_name, 

25 *args, 

26 **kwargs, 

27 ) 

28 

29 

30class ActionColumn(CustomTemplateColumn): 

31 """ 

32 A custom template column with some additional attributes 

33 for actions. 

34 """ 

35 

36 orderable = False 

37 exclude_from_export = True 

38 attrs = {"td": {"style": "width:1%;"}, "th": {"style": "font-size: 0"}} 

39 

40 def render(self, record, table, *args, **kwargs): 

41 if permission := getattr(self, "permission", False): 

42 if not table.request.user.has_perm(permission_fullname(permission, record)): 

43 return "" 

44 return super().render(record, table, *args, **kwargs) 

45 

46 

47class DeleteColumn(ActionColumn): 

48 """ 

49 A column showing a delete button 

50 """ 

51 

52 template_name = "columns/delete.html" 

53 permission = "delete" 

54 

55 

56class DuplicateColumn(ActionColumn): 

57 """ 

58 A column showing a duplicate button 

59 """ 

60 

61 template_name = "columns/duplicate.html" 

62 permission = "create" 

63 verbose_name = "duplicate" 

64 

65 

66class EditColumn(ActionColumn): 

67 """ 

68 A column showing an edit button 

69 """ 

70 

71 template_name = "columns/edit.html" 

72 permission = "change" 

73 

74 

75class ViewColumn(ActionColumn): 

76 """ 

77 A column showing a view button 

78 """ 

79 

80 template_name = "columns/view.html" 

81 permission = "view" 

82 

83 

84class DescriptionColumn(CustomTemplateColumn): 

85 """ 

86 A column showing a model description 

87 """ 

88 

89 template_name = "columns/description.html" 

90 orderable = False 

91 

92 

93class GenericTable(tables.Table): 

94 """ 

95 A generic table that contains an edit button column, a delete button column 

96 and a description column 

97 """ 

98 

99 edit = EditColumn() 

100 desc = DescriptionColumn() 

101 delete = DeleteColumn() 

102 view = ViewColumn() 

103 noduplicate = DuplicateColumn() 

104 

105 class Meta: 

106 fields = ["id", "desc"] 

107 sequence = ("...", "view", "edit", "delete", "noduplicate") 

108 

109 

110class MoreLessColumn(tables.TemplateColumn): 

111 """ 

112 Useful for displaying long fields. 

113 A preview is shown initially with a "Show more" link 

114 which is replaced with a "Show less" link when expanded. 

115 """ 

116 

117 template_name = "columns/more-less.html" 

118 

119 def __init__(self, preview, fulltext, *args, **kwargs): 

120 self.preview = preview 

121 self.fulltext = fulltext 

122 super().__init__(template_name=self.template_name, *args, **kwargs) 

123 

124 def render(self, record, **kwargs): 

125 self.extra_context["preview"] = self.preview(record) 

126 self.extra_context["fulltext"] = self.fulltext(record) 

127 return super().render(record, **kwargs)