Coverage for src/django_resume/views.py: 100%
66 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-10-13 13:17 +0200
« prev ^ index » next coverage.py v7.6.1, created at 2024-10-13 13:17 +0200
1from typing import Any
3from django.contrib.auth.decorators import login_required
4from django import forms
5from django.http import HttpRequest, HttpResponse
6from django.shortcuts import render, get_object_or_404
7from django.views.decorators.http import require_http_methods
9from .models import Resume
10from .plugins import plugin_registry
13def get_edit_and_show_urls(request: HttpRequest) -> tuple[str, str]:
14 query_params = request.GET.copy()
15 if "edit" in query_params:
16 query_params.pop("edit")
18 show_url = f"{request.path}?{query_params.urlencode()}"
19 query_params["edit"] = "true"
20 edit_url = f"{request.path}?{query_params.urlencode()}"
21 return edit_url, show_url
24def resume_cv(request: HttpRequest, slug: str) -> HttpResponse:
25 """
26 Show a CV view of the resume.
28 By default, you need a token to be able to see the CV.
29 """
30 resume = get_object_or_404(Resume.objects.select_related("owner"), slug=slug)
32 edit = bool(dict(request.GET).get("edit", False))
33 is_editable = request.user.is_authenticated and resume.owner == request.user
34 show_edit_button = True if is_editable and edit else False
36 edit_url, show_url = get_edit_and_show_urls(request)
37 context = {
38 "resume": resume,
39 "timelines": [],
40 "projects": [],
41 # needed to include edit styles in the base template
42 "show_edit_button": show_edit_button,
43 "is_editable": is_editable,
44 "edit_url": edit_url,
45 "show_url": show_url,
46 }
47 for plugin in plugin_registry.get_all_plugins():
48 context[plugin.name] = plugin.get_context(
49 request,
50 plugin.get_data(resume),
51 resume.pk,
52 context={},
53 edit=show_edit_button,
54 )
55 return render(request, "django_resume/plain/resume_cv.html", context=context)
58def resume_detail(request: HttpRequest, slug: str) -> HttpResponse:
59 """
60 The main resume detail view.
62 At the moment, it is used for the cover letter.
63 """
64 resume = get_object_or_404(Resume.objects.select_related("owner"), slug=slug)
66 edit = bool(dict(request.GET).get("edit", False))
67 is_editable = request.user.is_authenticated and resume.owner == request.user
68 show_edit_button = True if is_editable and edit else False
70 edit_url, show_url = get_edit_and_show_urls(request)
71 context = {
72 "resume": resume,
73 # needed to include edit styles in the base template
74 "show_edit_button": show_edit_button,
75 "is_editable": is_editable,
76 "edit_url": edit_url,
77 "show_url": show_url,
78 }
79 plugin_names = ["about", "identity", "cover"]
80 for name in plugin_names:
81 plugin = plugin_registry.get_plugin(name)
82 context[plugin.name] = plugin.get_context(
83 request,
84 plugin.get_data(resume),
85 resume.pk,
86 context={},
87 edit=show_edit_button,
88 )
89 return render(request, "django_resume/plain/resume_detail.html", context=context)
92class ResumeForm(forms.ModelForm):
93 class Meta:
94 model = Resume
95 fields = ["name", "slug"]
98@login_required
99@require_http_methods(["GET", "POST"])
100def resume_list(request: HttpRequest) -> HttpResponse:
101 """
102 The main resume list view. Only authenticated users can see it.
104 You can add and delete your resumes from this view.
105 """
106 assert request.user.is_authenticated # type guard just to make mypy happy
107 my_resumes = Resume.objects.filter(owner=request.user)
108 context: dict[str, Any] = {
109 "is_editable": True, # needed to include edit styles in the base
110 "resumes": my_resumes,
111 "form": ResumeForm(),
112 }
113 if request.method == "POST":
114 form = ResumeForm(request.POST)
115 context["form"] = form
116 if form.is_valid():
117 resume = form.save(commit=False)
118 resume.owner = request.user
119 resume.save()
120 context["new_resume"] = resume
121 return render(
122 request, "django_resume/plain/resume_list_main.html", context=context
123 )
124 else:
125 # just render the complete template on GET
126 return render(request, "django_resume/plain/resume_list.html", context=context)
129@login_required
130@require_http_methods(["DELETE"])
131def resume_delete(request: HttpRequest, slug: str) -> HttpResponse:
132 """
133 Delete a resume.
135 Only the owner of the resume can delete it.
136 """
137 resume = get_object_or_404(Resume, slug=slug)
138 if resume.owner != request.user:
139 return HttpResponse(status=403)
141 resume.delete()
142 return HttpResponse(status=200) # 200 instead of 204 for htmx compatibility