Coverage for website/documents/views.py: 58.49%

43 statements  

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

1import os 

2from collections import defaultdict 

3 

4from django.conf import settings 

5from django.core.exceptions import PermissionDenied 

6from django.http import Http404, HttpResponse 

7from django.shortcuts import redirect 

8from django.urls import reverse 

9from django.utils import timezone 

10from django.utils.text import slugify 

11from django.views.generic import DetailView, TemplateView 

12 

13from documents.models import ( 

14 AnnualDocument, 

15 AssociationDocument, 

16 Document, 

17 GeneralMeeting, 

18) 

19from utils.media.services import get_media_url 

20from utils.snippets import datetime_to_lectureyear 

21 

22 

23class DocumentsIndexView(TemplateView): 

24 """View that renders the documents index page.""" 

25 

26 template_name = "documents/index.html" 

27 

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

29 lecture_year = datetime_to_lectureyear(timezone.now()) 

30 

31 years = defaultdict( 

32 lambda: { 

33 "documents": {c: None for c in AnnualDocument.Subcategory.values}, 

34 "general_meetings": [], 

35 } 

36 ) 

37 

38 # Ensure that all years up to now are in the dict, even if there are no documents. 

39 # Using a defaultdict means that future years will be added automatically iff a 

40 # document exists for that year, such as a policy plan for the upcoming year. 

41 for year in range(1990, lecture_year + 1): 

42 years[year] = years[year] 

43 

44 for document in AnnualDocument.objects.all(): 

45 years[document.year]["documents"][document.subcategory] = document 

46 

47 for obj in GeneralMeeting.objects.all(): 

48 meeting_year = datetime_to_lectureyear(obj.datetime) 

49 years[meeting_year]["general_meetings"].append(obj) 

50 

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

52 context.update( 

53 { 

54 "association_documents": AssociationDocument.objects.order_by( 

55 "name" 

56 ).all(), 

57 "years": sorted(years.items(), reverse=True), 

58 } 

59 ) 

60 return context 

61 

62 

63class DocumentDownloadView(DetailView): 

64 """View that allows you to download a specific document based on it's and your permissions settings.""" 

65 

66 model = Document 

67 

68 def get(self, request, *args, **kwargs) -> HttpResponse: 

69 response = super().get(request, *args, **kwargs) 

70 document = response.context_data["document"] 

71 

72 if document.members_only and not request.user.is_authenticated: 

73 return redirect(reverse(settings.LOGIN_URL) + f"?next={request.path}") 

74 if document.members_only and not request.member.has_active_membership(): 74 ↛ 75line 74 didn't jump to line 75 because the condition on line 74 was never true

75 raise PermissionDenied 

76 

77 try: 

78 file = document.file 

79 except ValueError as e: 

80 raise Http404("This document does not exist.") from e 

81 

82 ext = os.path.splitext(file.name)[1] 

83 

84 return redirect(get_media_url(file, attachment=slugify(document.name) + ext))