Coverage for cookbook/views/delete.py: 51%

152 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2023-12-29 00:47 +0100

1from django.contrib import messages 

2from django.db import models 

3from django.db.models import ProtectedError 

4from django.http import HttpResponseRedirect 

5from django.shortcuts import get_object_or_404, render 

6from django.urls import reverse, reverse_lazy 

7from django.utils.translation import gettext as _ 

8from django.views.generic import DeleteView 

9 

10from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required 

11from cookbook.models import (Comment, InviteLink, MealPlan, Recipe, RecipeBook, RecipeBookEntry, 

12 RecipeImport, Space, Storage, Sync, UserSpace) 

13from cookbook.provider.dropbox import Dropbox 

14from cookbook.provider.local import Local 

15from cookbook.provider.nextcloud import Nextcloud 

16 

17 

18class RecipeDelete(GroupRequiredMixin, DeleteView): 

19 groups_required = ['user'] 

20 template_name = "generic/delete_template.html" 

21 model = Recipe 

22 success_url = reverse_lazy('index') 

23 

24 def delete(self, request, *args, **kwargs): 

25 self.object = self.get_object() 

26 # TODO make this more generic so that all delete functions benefit from this 

27 if self.get_context_data()['protected_objects']: 

28 return render(request, template_name=self.template_name, context=self.get_context_data()) 

29 

30 success_url = self.get_success_url() 

31 self.object.delete() 

32 return HttpResponseRedirect(success_url) 

33 

34 def get_context_data(self, **kwargs): 

35 context = super(RecipeDelete, self).get_context_data(**kwargs) 

36 context['title'] = _("Recipe") 

37 

38 # TODO make this more generic so that all delete functions benefit from this 

39 self.object = self.get_object() 

40 context['protected_objects'] = [] 

41 context['cascading_objects'] = [] 

42 context['set_null_objects'] = [] 

43 for x in self.object._meta.get_fields(): 

44 try: 

45 related = x.related_model.objects.filter(**{x.field.name: self.object}) 

46 if related.exists() and x.on_delete == models.PROTECT: 

47 context['protected_objects'].append(related) 

48 if related.exists() and x.on_delete == models.CASCADE: 

49 context['cascading_objects'].append(related) 

50 if related.exists() and x.on_delete == models.SET_NULL: 

51 context['set_null_objects'].append(related) 

52 except AttributeError: 

53 pass 

54 

55 return context 

56 

57 

58@group_required('user') 

59def delete_recipe_source(request, pk): 

60 recipe = get_object_or_404(Recipe, pk=pk, space=request.space) 

61 

62 if recipe.storage.method == Storage.DROPBOX: 

63 # TODO central location to handle storage type switches 

64 Dropbox.delete_file(recipe) 

65 if recipe.storage.method == Storage.NEXTCLOUD: 

66 Nextcloud.delete_file(recipe) 

67 if recipe.storage.method == Storage.LOCAL: 

68 Local.delete_file(recipe) 

69 

70 recipe.storage = None 

71 recipe.file_path = '' 

72 recipe.file_uid = '' 

73 recipe.save() 

74 

75 return HttpResponseRedirect(reverse('edit_recipe', args=[recipe.pk])) 

76 

77 

78class RecipeImportDelete(GroupRequiredMixin, DeleteView): 

79 groups_required = ['user'] 

80 template_name = "generic/delete_template.html" 

81 model = RecipeImport 

82 success_url = reverse_lazy('list_recipe_import') 

83 

84 def get_context_data(self, **kwargs): 

85 context = super(RecipeImportDelete, self).get_context_data(**kwargs) 

86 context['title'] = _("Import") 

87 return context 

88 

89 

90class SyncDelete(GroupRequiredMixin, DeleteView): 

91 groups_required = ['admin'] 

92 template_name = "generic/delete_template.html" 

93 model = Sync 

94 success_url = reverse_lazy('data_sync') 

95 

96 def get_context_data(self, **kwargs): 

97 context = super(SyncDelete, self).get_context_data(**kwargs) 

98 context['title'] = _("Monitor") 

99 return context 

100 

101 

102class StorageDelete(GroupRequiredMixin, DeleteView): 

103 groups_required = ['admin'] 

104 template_name = "generic/delete_template.html" 

105 model = Storage 

106 success_url = reverse_lazy('list_storage') 

107 

108 def get_context_data(self, **kwargs): 

109 context = super(StorageDelete, self).get_context_data(**kwargs) 

110 context['title'] = _("Storage Backend") 

111 return context 

112 

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

114 try: 

115 return self.delete(request, *args, **kwargs) 

116 except ProtectedError: 

117 messages.add_message( 

118 request, 

119 messages.WARNING, 

120 _('Could not delete this storage backend as it is used in at least one monitor.') # noqa: E501 

121 ) 

122 return HttpResponseRedirect(reverse('list_storage')) 

123 

124 

125class CommentDelete(OwnerRequiredMixin, DeleteView): 

126 template_name = "generic/delete_template.html" 

127 model = Comment 

128 success_url = reverse_lazy('index') 

129 

130 def get_context_data(self, **kwargs): 

131 context = super(CommentDelete, self).get_context_data(**kwargs) 

132 context['title'] = _("Comment") 

133 return context 

134 

135 

136class RecipeBookDelete(OwnerRequiredMixin, DeleteView): 

137 template_name = "generic/delete_template.html" 

138 model = RecipeBook 

139 success_url = reverse_lazy('view_books') 

140 

141 def get_context_data(self, **kwargs): 

142 context = super(RecipeBookDelete, self).get_context_data(**kwargs) 

143 context['title'] = _("Recipe Book") 

144 return context 

145 

146 

147class RecipeBookEntryDelete(OwnerRequiredMixin, DeleteView): 

148 groups_required = ['user'] 

149 template_name = "generic/delete_template.html" 

150 model = RecipeBookEntry 

151 success_url = reverse_lazy('view_books') 

152 

153 def get_context_data(self, **kwargs): 

154 context = super(RecipeBookEntryDelete, self).get_context_data(**kwargs) 

155 context['title'] = _("Bookmarks") 

156 return context 

157 

158 

159class MealPlanDelete(OwnerRequiredMixin, DeleteView): 

160 template_name = "generic/delete_template.html" 

161 model = MealPlan 

162 success_url = reverse_lazy('view_plan') 

163 

164 def get_context_data(self, **kwargs): 

165 context = super(MealPlanDelete, self).get_context_data(**kwargs) 

166 context['title'] = _("Meal-Plan") 

167 return context 

168 

169 

170class InviteLinkDelete(OwnerRequiredMixin, DeleteView): 

171 template_name = "generic/delete_template.html" 

172 model = InviteLink 

173 success_url = reverse_lazy('list_invite_link') 

174 

175 def get_context_data(self, **kwargs): 

176 context = super(InviteLinkDelete, self).get_context_data(**kwargs) 

177 context['title'] = _("Invite Link") 

178 return context 

179 

180 

181class UserSpaceDelete(OwnerRequiredMixin, DeleteView): 

182 template_name = "generic/delete_template.html" 

183 model = UserSpace 

184 success_url = reverse_lazy('view_space_overview') 

185 

186 def get_context_data(self, **kwargs): 

187 context = super(UserSpaceDelete, self).get_context_data(**kwargs) 

188 context['title'] = _("Space Membership") 

189 return context 

190 

191 

192class SpaceDelete(OwnerRequiredMixin, DeleteView): 

193 template_name = "generic/delete_template.html" 

194 model = Space 

195 success_url = reverse_lazy('view_space_overview') 

196 

197 def delete(self, request, *args, **kwargs): 

198 self.object = self.get_object() 

199 self.object.safe_delete() 

200 return HttpResponseRedirect(self.get_success_url()) 

201 

202 def get_context_data(self, **kwargs): 

203 context = super(SpaceDelete, self).get_context_data(**kwargs) 

204 context['title'] = _("Space") 

205 return context