Coverage for website/facedetection/views.py: 46.43%

78 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2025-08-14 10:31 +0000

1from django.conf import settings 

2from django.contrib import messages 

3from django.contrib.auth.mixins import LoginRequiredMixin 

4from django.core.exceptions import ValidationError 

5from django.http import HttpResponseRedirect 

6from django.shortcuts import redirect 

7from django.urls import reverse_lazy 

8from django.utils import timezone 

9from django.utils.translation import gettext_lazy as _ 

10from django.views.generic import DeleteView, FormView, ListView 

11 

12from photos.models import Photo 

13from thaliawebsite.views import PagedView 

14 

15from .forms import ReferenceFaceUploadForm 

16from .models import ReferenceFace 

17from .services import get_user_photos 

18 

19 

20class YourPhotosView(LoginRequiredMixin, PagedView): 

21 model = Photo 

22 paginate_by = 50 

23 template_name = "facedetection/your-photos.html" 

24 context_object_name = "photos" 

25 

26 def get(self, request, *args, **kwargs): 

27 if not request.member or not request.member.has_active_membership(): 

28 messages.error(request, _("You need to be a member to use this feature.")) 

29 return redirect("index") 

30 

31 return super().get(request, *args, **kwargs) 

32 

33 def get_queryset(self): 

34 return get_user_photos(self.request.member) 

35 

36 def get_context_data(self, **kwargs): 

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

38 

39 context["has_processing_reference_faces"] = ( 

40 self.request.member.reference_faces.filter( 

41 status=ReferenceFace.Status.PROCESSING, 

42 marked_for_deletion_at__isnull=True, 

43 ).exists() 

44 ) 

45 

46 context["has_rejected_reference_faces"] = ( 

47 self.request.member.reference_faces.filter( 

48 status=ReferenceFace.Status.REJECTED, 

49 marked_for_deletion_at__isnull=True, 

50 ).exists() 

51 ) 

52 

53 context["has_reference_faces"] = self.request.member.reference_faces.filter( 

54 marked_for_deletion_at__isnull=True 

55 ).exists() 

56 

57 return context 

58 

59 

60class ReferenceFaceView(LoginRequiredMixin, ListView): 

61 template_name = "facedetection/reference-faces.html" 

62 

63 def get_context_data(self, **kwargs): 

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

65 context["reference_faces_limit"] = ( 

66 settings.FACEDETECTION_MAX_NUM_REFERENCE_FACES 

67 ) 

68 context["storage_period_after_delete"] = ( 

69 settings.FACEDETECTION_REFERENCE_FACE_STORAGE_PERIOD_AFTER_DELETE_DAYS 

70 ) 

71 context["reference_faces_limit_reached"] = bool( 

72 self.request.member.reference_faces.filter( 

73 marked_for_deletion_at__isnull=True 

74 ).count() 

75 >= settings.FACEDETECTION_MAX_NUM_REFERENCE_FACES 

76 ) 

77 context["has_rejected_reference_faces"] = ( 

78 self.request.member.reference_faces.filter( 

79 status=ReferenceFace.Status.REJECTED, 

80 marked_for_deletion_at__isnull=True, 

81 ).exists() 

82 ) 

83 return context 

84 

85 def get_queryset(self): 

86 return self.request.member.reference_faces.filter( 

87 marked_for_deletion_at__isnull=True 

88 ).all() 

89 

90 

91class ReferenceFaceUploadView(LoginRequiredMixin, FormView): 

92 template_name = "facedetection/reference-face-upload.html" 

93 form_class = ReferenceFaceUploadForm 

94 success_url = reverse_lazy("facedetection:reference-faces") 

95 

96 def dispatch(self, request, *args, **kwargs): 

97 if not request.member or not request.member.has_active_membership(): 

98 messages.error(request, "You need to be a member to use this feature.") 

99 return redirect("index") 

100 return super().dispatch(request, *args, **kwargs) 

101 

102 def form_valid(self, form): 

103 try: 

104 form.save(user=self.request.member) 

105 except ValidationError as e: 

106 for error in e: 

107 messages.error(self.request, error) 

108 return self.form_invalid(form) 

109 messages.success(self.request, "Your reference face has been uploaded.") 

110 return super().form_valid(form) 

111 

112 

113class ReferenceFaceDeleteView(LoginRequiredMixin, DeleteView): 

114 model = ReferenceFace 

115 success_url = reverse_lazy("facedetection:reference-faces") 

116 

117 def get_context_data(self, **kwargs): 

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

119 context["storage_period_after_delete"] = ( 

120 settings.FACEDETECTION_REFERENCE_FACE_STORAGE_PERIOD_AFTER_DELETE_DAYS 

121 ) 

122 return context 

123 

124 def get_queryset(self): 

125 return self.request.member.reference_faces.filter( 

126 marked_for_deletion_at__isnull=True 

127 ).all() 

128 

129 def form_valid(self, form): 

130 success_url = self.get_success_url() 

131 

132 instance = self.get_object() 

133 instance.marked_for_deletion_at = timezone.now() 

134 instance.save() 

135 messages.success(self.request, "Your reference face has been deleted.") 

136 

137 return HttpResponseRedirect(success_url)