Coverage for website/views/AuthorView.py: 81%
169 statements
« prev ^ index » next coverage.py v7.5.0, created at 2025-09-13 15:29 -0300
« prev ^ index » next coverage.py v7.5.0, created at 2025-09-13 15:29 -0300
1from django.contrib import messages
2from django.contrib.auth import update_session_auth_hash
3from django.forms import inlineformset_factory
4from django.shortcuts import get_object_or_404, redirect, render
6from website.forms.EditAuthorForm import (
7 EditAuthorForm,
8 GraduationForm,
9 JobForm,
10 SocialMediaForm,
11 UserChangeForm,
12)
13from website.models import User
14from website.models.__init__ import ACADEMIC_LEVEL, SOCIAL_MEDIA
15from website.models.AuthorModel import Author
16from website.models.AuthorSocialMediaModel import SocialMedia
17from website.models.GraduationsModel import Graduation
18from website.models.JobsModel import Job
21def view_author_page(request, slug):
22 author = get_object_or_404(Author, author_url_slug=slug)
23 context = {
24 "author": author,
25 "author_connected": False,
26 "social_media_index": SOCIAL_MEDIA,
27 "graduations_level": ACADEMIC_LEVEL,
28 }
29 if request.user != author.user:
30 return render(
31 request, template_name="author/author.html", context=context, status=200
32 )
33 context["author_connected"] = True
34 return render(
35 request, template_name="author/author.html", context=context, status=200
36 )
39def edit_author_profile(request, slug):
40 author = get_object_or_404(Author, author_url_slug=slug)
41 author_social_media = author.social_media.all()
42 form = EditAuthorForm(instance=author)
43 user_form = UserChangeForm(instance=request.user)
44 social_forms = []
45 for social in author_social_media:
46 social_forms.append(SocialMediaForm(instance=social))
47 social_empty_form = SocialMediaForm()
48 send_message = False
50 # create formset factory here (safe even if GraduationFormSet defined later)
51 GraduationFormSetLocal = inlineformset_factory(
52 Author, Graduation, form=GraduationForm, extra=0, can_delete=True
53 )
54 JobFormSetLocal = inlineformset_factory(
55 Author, Job, form=JobForm, extra=0, can_delete=True
56 )
58 if request.POST:
59 # rebind user and author forms with POST data
60 user_form = UserChangeForm(request.POST, instance=request.user)
61 author_form = EditAuthorForm(request.POST, request.FILES, instance=author)
63 # instantiate formset with POST (and FILES) and try to detect prefix
64 prefix = None
65 for k in request.POST.keys():
66 if k.endswith("-TOTAL_FORMS") and "gradu" in k.lower():
67 prefix = k.rsplit("-TOTAL_FORMS", 1)[0]
68 break
69 if prefix is None:
70 for k in request.POST.keys():
71 if k.endswith("-TOTAL_FORMS"):
72 prefix = k.rsplit("-TOTAL_FORMS", 1)[0]
73 break
75 # try to detect graduation vs job prefix separately
76 grad_prefix = None
77 job_prefix = None
78 for k in request.POST.keys():
79 if k.endswith("-TOTAL_FORMS"):
80 low = k.lower()
81 if "gradu" in low:
82 grad_prefix = k.rsplit("-TOTAL_FORMS", 1)[0]
83 if "job" in low or "jobs" in low:
84 job_prefix = k.rsplit("-TOTAL_FORMS", 1)[0]
86 if grad_prefix:
87 graduation_formset = GraduationFormSetLocal(
88 request.POST, request.FILES, instance=author, prefix=grad_prefix
89 )
90 else:
91 graduation_formset = GraduationFormSetLocal(
92 request.POST, request.FILES, instance=author
93 )
95 if job_prefix:
96 job_formset = JobFormSetLocal(
97 request.POST, request.FILES, instance=author, prefix=job_prefix
98 )
99 else:
100 job_formset = JobFormSetLocal(request.POST, request.FILES, instance=author)
102 # (debug logs removed)
104 # rebind social forms with POST
105 social_forms = []
106 for social in author_social_media:
107 social_forms.append(SocialMediaForm(request.POST, instance=social))
109 author_request_post = check_request_post(request)
110 if author_request_post is not None:
111 if author.image != "" and author_request_post["image"] is not None:
112 author.image.delete(save=True)
113 author.image = author_request_post["image"]
115 # validate forms
116 forms_ok = True
118 # (debug logs removed)
120 # username conflict check
121 username_conflict = False
122 if author_request_post:
123 username_conflict = bool(author_request_post.get("check_username_request"))
124 if not user_form.is_valid() or username_conflict:
125 forms_ok = False
126 if username_conflict:
127 messages.error(request, "Nome de usuário já está em uso.")
129 if not author_form.is_valid():
130 forms_ok = False
132 # validate graduation formset
133 if not graduation_formset.is_valid():
134 forms_ok = False
136 # validate job formset
137 if not job_formset.is_valid():
138 forms_ok = False
140 if forms_ok:
141 # save user (handle password: preserve original if empty)
142 original_password = request.user.password
143 user = user_form.save(commit=False)
144 pw = user_form.cleaned_data.get("password")
145 if pw:
146 user.set_password(pw)
147 # keep the current session authenticated after a password change
148 try:
149 update_session_auth_hash(request, user)
150 except Exception:
151 # be conservative: if session update fails, continue and let
152 # Django's auth system handle the next request
153 pass
154 else:
155 # preserve original hashed password
156 user.password = original_password
157 user.save()
159 # save author
160 author = author_form.save()
162 # update social media entries
163 if update_social_media(request, author_social_media):
164 send_message = True
165 # create new social media if requested
166 if (
167 author_request_post
168 and author_request_post.get("new_social_addition")
169 and not any(author_request_post.get("exclude_social_media", []))
170 ):
171 create_social_media(request, author_request_post)
172 send_message = True
173 # exclude if requested
174 if author_request_post and any(
175 author_request_post.get("exclude_social_media", [])
176 ):
177 exclude_social_media(request, author)
178 send_message = True
180 # save graduation formset (instance already saved)
181 graduation_formset.instance = author
182 graduation_formset.save()
183 # save jobs
184 job_formset.instance = author
185 job_formset.save()
186 send_message = True
188 if send_message:
189 messages.success(request, "Dados atualizados com sucesso.")
190 return redirect("author", slug=author.author_url_slug)
191 else:
192 # render page with errors (no redirect)
193 context = {
194 "socialEmptyForm": social_empty_form,
195 "userForm": user_form,
196 "authorForm": author_form,
197 "socialForms": social_forms,
198 "academic_levels": ACADEMIC_LEVEL,
199 "graduation_formset": graduation_formset,
200 "job_formset": job_formset,
201 }
202 return render(
203 request,
204 template_name="edit-author/edit-author.html",
205 context=context,
206 )
207 else:
208 # GET: provide an empty/loaded formset instance
209 graduation_formset = GraduationFormSetLocal(instance=author)
210 job_formset = JobFormSetLocal(instance=author)
212 context = {
213 "socialEmptyForm": social_empty_form,
214 "userForm": user_form,
215 "authorForm": form,
216 "socialForms": social_forms,
217 "academic_levels": ACADEMIC_LEVEL,
218 "graduation_formset": graduation_formset,
219 "job_formset": job_formset,
220 }
221 return render(
222 request, template_name="edit-author/edit-author.html", context=context
223 )
226def check_request_post(request):
227 author_post_request_data = None
228 if request.POST:
229 author_post_request_data = {
230 "username": request.POST["username"],
231 "name": request.POST["author_name"],
232 "check_username_request": Author.objects.filter(
233 user__username=request.POST["username"]
234 )
235 .exclude(user__id=request.user.id)
236 .first(),
237 "image": request.FILES.get("image", None),
238 "new_social_addition": len(request.POST.getlist("social_media_profile"))
239 > len(
240 Author.objects.get(
241 user__username=request.POST["username"]
242 ).social_media.all()
243 ),
244 "exclude_social_media": request.POST.getlist("exclude-social"),
245 }
247 return author_post_request_data
250def check_user_form(request, author):
251 user_form = UserChangeForm(request.POST, instance=request.user)
252 author_user = check_request_post(request)
253 username_free = author_user["check_username_request"] != author.user.username
254 if (
255 user_form.is_valid()
256 and author_user["username"] != author.user.username
257 and username_free
258 ):
259 user_author = get_object_or_404(User, id=author.user.id)
260 user_author.username = author_user["username"]
261 user_author.save()
262 return username_free
265def check_author_form(request, author):
266 author_form = EditAuthorForm(request.POST, request.FILES, instance=author)
267 check_post = check_request_post(request)
268 if author_form.is_valid():
269 author.author_name = check_post["name"]
270 author.save()
271 return True
272 return False
275def update_social_media(request, author_social_media):
276 social_media_request_post = list(
277 zip(
278 request.POST.getlist("social_media"),
279 request.POST.getlist("social_media_profile"),
280 )
281 )
282 updated = False
283 for i in range(len(author_social_media)):
284 if (
285 author_social_media[i].social_media != int(social_media_request_post[i][0])
286 ) or (
287 author_social_media[i].social_media_profile
288 != social_media_request_post[i][1]
289 ):
290 author_social_media[i].social_media = social_media_request_post[i][0]
291 author_social_media[i].social_media_profile = social_media_request_post[i][
292 1
293 ]
294 author_social_media[i].save()
295 updated = True
296 return updated
299def create_social_media(request, author_request_post):
300 social_media_request_post = list(
301 zip(
302 request.POST.getlist("social_media"),
303 request.POST.getlist("social_media_profile"),
304 )
305 )
306 author = Author.objects.get(user__username=author_request_post["username"])
307 social = author.social_media.all()
309 for i in range(len(social), len(social_media_request_post)):
310 new_social = SocialMedia.objects.create(
311 user_social_media=author,
312 social_media=social_media_request_post[i][0],
313 social_media_profile=social_media_request_post[i][1],
314 )
315 new_social.save()
316 author.social_media.add(new_social)
319def exclude_social_media(request, author):
320 exclusions = check_request_post(request)["exclude_social_media"]
321 for exclude_request in exclusions:
322 if exclude_request != "":
323 # directly delete the matched social media entry
324 author.social_media.get(social_media=exclude_request).delete()
327def set_graduation():
328 pass
331def edit_author(request, author_slug=None):
332 """Wrapper to keep compatibility: delegate to edit_author_profile.
334 If no author_slug is provided, use the logged-in user's author slug.
335 """
336 if not author_slug:
337 if hasattr(request, "user") and getattr(request.user, "author", None):
338 slug = request.user.author.author_url_slug
339 else:
340 # nothing sensible to edit; redirect to home
341 return redirect("/")
342 else:
343 slug = author_slug
344 return edit_author_profile(request, slug)