Coverage for server / views.py: 74%

84 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-24 12:43 +0000

1from django.contrib.auth.mixins import LoginRequiredMixin 

2from django.contrib import messages 

3 

4from sm.views import SafeDeleteMixin 

5from sm.mixins import MultiTenantMixin 

6 

7from .models import Model 

8from .forms import Form, FormDisabled, BulkActionForm 

9from . import app_label 

10 

11from django.views import View 

12from django.shortcuts import redirect 

13 

14from django.views.generic import ListView as GenericListView 

15from django.views.generic.edit import UpdateView as GenericUpdateView 

16from django.views.generic.edit import CreateView as GenericCreateView 

17from django.views.generic.edit import DeleteView as GenericDeleteView 

18 

19from django.contrib.messages.views import SuccessMessageMixin 

20 

21from django.utils.translation import gettext as _ 

22 

23try: 

24 from django.urls import reverse_lazy 

25except Exception: # pragma: no cover 

26 from django.urls import reverse_lazy # pragma: no cover 

27 

28 

29class ListView(LoginRequiredMixin, MultiTenantMixin, GenericListView): 

30 template_name = "%s/list.html" % app_label 

31 model = Model 

32 paginate_by = 20 

33 paginate_orphans = paginate_by / 4 

34 # queryset = model.objects.all() 

35 ordering = "hostname" 

36 

37 def get_queryset(self): 

38 queryset = super().get_queryset() 

39 if "srvmanager-show_disposed" in self.request.COOKIES: 

40 if self.request.COOKIES["srvmanager-show_disposed"] == "true": 

41 return queryset.order_by(self.ordering) 

42 return queryset.exclude(status__name="Disposed").order_by(self.ordering) 

43 

44 def get_context_data(self, **kwargs): 

45 context = super().get_context_data(**kwargs) 

46 context["bulk_form"] = BulkActionForm() 

47 return context 

48 

49 

50class BulkActionView(LoginRequiredMixin, MultiTenantMixin, View): 

51 def post(self, request, *args, **kwargs): 

52 server_ids = request.POST.getlist("selected_servers") 

53 if not server_ids: 

54 messages.warning(request, _("No servers selected.")) 

55 return redirect("server:index") 

56 

57 form = BulkActionForm(request.POST) 

58 if form.is_valid(): 

59 # Use get_queryset to ensure multi-tenancy filtering 

60 servers = self.get_queryset().filter(id__in=server_ids) 

61 count = servers.count() 

62 

63 if form.cleaned_data["delete"]: 

64 # Check delete permission 

65 if not request.user.has_perm("server.delete_model"): 

66 messages.error( 

67 request, 

68 _("You don't have permission to delete servers."), 

69 ) 

70 return redirect("server:index") 

71 servers.delete() 

72 messages.success(request, _("Successfully deleted %d servers.") % count) 

73 elif form.cleaned_data["status"]: 

74 new_status = form.cleaned_data["status"] 

75 for server in servers: 

76 server.status = new_status 

77 server.save() 

78 messages.success( 

79 request, 

80 _("Successfully updated status to %s for %d servers.") 

81 % (new_status, count), 

82 ) 

83 else: 

84 messages.info(request, _("No action performed.")) 

85 

86 return redirect("server:index") 

87 

88 

89class DetailView(LoginRequiredMixin, MultiTenantMixin, GenericUpdateView): 

90 template_name = "%s/detail.html" % app_label 

91 model = Model 

92 form_class = FormDisabled 

93 

94 

95class UpdateView( 

96 SuccessMessageMixin, 

97 LoginRequiredMixin, 

98 MultiTenantMixin, 

99 GenericUpdateView, 

100): 

101 success_message = "%(hostname)s " + _("was updated successfully") 

102 model = Model 

103 

104 template_name = "%s/edit.html" % app_label 

105 form_class = Form 

106 success_url = reverse_lazy("%s:index" % app_label) 

107 

108 

109class CreateView( 

110 SuccessMessageMixin, 

111 LoginRequiredMixin, 

112 MultiTenantMixin, 

113 GenericCreateView, 

114): 

115 success_message = "%(hostname)s " + _("was created successfully") 

116 model = Model 

117 

118 template_name = "%s/edit.html" % app_label 

119 form_class = Form 

120 success_url = reverse_lazy("%s:index" % app_label) 

121 

122 

123class DeleteView( 

124 SafeDeleteMixin, 

125 LoginRequiredMixin, 

126 MultiTenantMixin, 

127 GenericDeleteView, 

128): 

129 success_message = "%(hostname)s " + _("was deleted successfully") 

130 template_name = "delete.html" 

131 model = Model 

132 success_url = reverse_lazy("%s:index" % app_label) 

133 

134 

135class SearchView(LoginRequiredMixin, MultiTenantMixin, GenericListView): 

136 template_name = "%s/list.html" % app_label 

137 model = Model 

138 paginate_by = 20 

139 paginate_orphans = paginate_by / 4 

140 ordering = "hostname"