add bulk edit grades

This commit is contained in:
Ross
2023-02-13 11:05:20 +00:00
parent 8b8b21b006
commit 4666294979
4 changed files with 234 additions and 53 deletions
+7 -2
View File
@@ -1,11 +1,16 @@
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
def user_is_cid_user_manager(function): def user_is_cid_user_manager(function):
def wrap(request, *args, **kwargs): def wrap(request, *args, **kwargs):
if request.user.groups.filter(name='cid_user_manager').exists() or request.user.is_superuser: if (
request.user.groups.filter(name="cid_user_manager").exists()
or request.user.is_superuser
):
return function(request, *args, **kwargs) return function(request, *args, **kwargs)
else: else:
raise PermissionDenied raise PermissionDenied
wrap.__doc__ = function.__doc__ wrap.__doc__ = function.__doc__
wrap.__name__ = function.__name__ wrap.__name__ = function.__name__
return wrap return wrap
+25 -11
View File
@@ -7,18 +7,18 @@
{% block content %} {% block content %}
<div id="view-filter-options"> <div id="view-filter-options">
<details class="filter"> <details class="filter">
<summary> <summary>
<h3>Filter Users </h3> <h3>Filter Users </h3>
</summary> </summary>
<form action="" method="get"> <form action="" method="get">
{{ filter.form }} {{ filter.form }}
<input class="btn btn-primary btn-sm mt-1 mb-1" type="submit" /> <input class="btn btn-primary btn-sm mt-1 mb-1" type="submit" />
</form> </form>
</details> </details>
</div> </div>
<div> <div id="table-div">
<span id="manage-span"> <span id="manage-span">
{% render_table table %} {% render_table table %}
</span> </span>
@@ -31,7 +31,21 @@
<summary> <summary>
Bulk edit Bulk edit
</summary> </summary>
<button>Delete supervisors</button> <div id="htmx-info"></div>
<div id="htmx-options"></div>
<button id="bulk-delete-supervisors-button"
title="Deletes the supervisors of all selected users"
hx-post="{% url 'generic:users_bulk_delete_supervisors' %}"
hx-include="[name='selection']"
hx-confirm="This will delete supervisors from all selected users, are you sure you wish to continue?"
hx-target="#htmx-info"
>Delete supervisors</button>
<button id="bulk-edit-grade-button"
hx-post="{% url 'generic:users_bulk_edit_grade' %}"
hx-include="[name='selection']"
hx-target="#htmx-options"
>Edit grade</button>
</details> </details>
{% endblock %} {% endblock %}
+14 -1
View File
@@ -77,6 +77,8 @@ urlpatterns = [
path( path(
"cids/group/create", views.CidUserGroupCreate.as_view(), name="cid_group_create" "cids/group/create", views.CidUserGroupCreate.as_view(), name="cid_group_create"
), ),
path("user/bulk_delete_supervisors/", views.users_bulk_delete_supervisors, name="users_bulk_delete_supervisors"),
path("user/bulk_edit_grade/", views.users_bulk_edit_grade, name="users_bulk_edit_grade"),
path("user/group/", views.user_group_view, name="user_group_view"), path("user/group/", views.user_group_view, name="user_group_view"),
path("user/group/all", views.user_group_view_all, name="user_group_view_all"), path("user/group/all", views.user_group_view_all, name="user_group_view_all"),
path("user/group/<int:group_id>/", views.user_group_view_detail, name="user_group_detail"), path("user/group/<int:group_id>/", views.user_group_view_detail, name="user_group_detail"),
@@ -246,16 +248,27 @@ def generic_exam_urls(generic_exam_view: GenericExamViews):
generic_exam_view.exam_json_cid_unbased, generic_exam_view.exam_json_cid_unbased,
name="exam_json_cid_unbased", name="exam_json_cid_unbased",
), ),
# These are a little more ambiguous than ideal
path( path(
"exam/json/<int:pk>/<int:sk>", "exam/json/<int:pk>/<int:sk>",
generic_exam_view.exam_question_json, generic_exam_view.exam_question_json,
name="exam_question_json_unbased", name="exam_question_json",
), ),
path( path(
"exam/json/<int:pk>/<int:sk>/unbased", "exam/json/<int:pk>/<int:sk>/unbased",
generic_exam_view.exam_question_json_unbased, generic_exam_view.exam_question_json_unbased,
name="exam_question_json_unbased", name="exam_question_json_unbased",
), ),
path(
"exam/json/<int:pk>/<int:cid>/<str:passcode>/<int:sk>",
generic_exam_view.exam_question_json_cid,
name="exam_question_json_cid",
),
path(
"exam/json/<int:pk>/<int:cid>/<str:passcode>/<int:sk>/unbased",
generic_exam_view.exam_question_json_unbased_cid,
name="exam_question_json_unbased_cid",
),
path( path(
"exam/json/<int:pk>/recreate", "exam/json/<int:pk>/recreate",
generic_exam_view.exam_json_recreate, generic_exam_view.exam_json_recreate,
+188 -39
View File
@@ -58,7 +58,19 @@ from .forms import (
UserUserGroupForm, UserUserGroupForm,
) )
from .models import CidUser, CidUserGroup, ExamBase, ExamUserStatus, Examination, QuestionNote, Supervisor, UserGrades, UserProfile, UserUserGroup, get_next_cid from .models import (
CidUser,
CidUserGroup,
ExamBase,
ExamUserStatus,
Examination,
QuestionNote,
Supervisor,
UserGrades,
UserProfile,
UserUserGroup,
get_next_cid,
)
from rapids.models import Rapid as RapidQuestion from rapids.models import Rapid as RapidQuestion
from rapids.models import Exam as RapidExam from rapids.models import Exam as RapidExam
@@ -355,6 +367,7 @@ class ExamViews(View, LoginRequiredMixin):
self.ExamFilter = ExamFilter self.ExamFilter = ExamFilter
# TODO: these may be better implemented as decorators
def check_user_access(self, user: User, exam_id: int = None): def check_user_access(self, user: User, exam_id: int = None):
"""Check if a user should be able to access a view """Check if a user should be able to access a view
@@ -479,9 +492,7 @@ class ExamViews(View, LoginRequiredMixin):
exam = get_object_or_404(self.Exam, pk=pk) exam = get_object_or_404(self.Exam, pk=pk)
exam.archive = ( exam.archive = True if request.POST.get("archive") == "true" else False
True if request.POST.get("archive") == "true" else False
)
print(f"{exam.archive=}") print(f"{exam.archive=}")
exam.save() exam.save()
data = { data = {
@@ -842,7 +853,7 @@ class ExamViews(View, LoginRequiredMixin):
"can_edit": can_edit, "can_edit": can_edit,
"notes": notes, "notes": notes,
"app_name": self.app_name, "app_name": self.app_name,
"candidate_count": (cid_candidates, users_candidates) "candidate_count": (cid_candidates, users_candidates),
}, },
) )
@@ -885,7 +896,7 @@ class ExamViews(View, LoginRequiredMixin):
Returns: Returns:
_type_: _description_ _type_: _description_
""" """
exam = get_object_or_404(self.Exam, pk=exam_id) exam = get_object_or_404(self.Exam, pk=exam_id)
# if not request.user.groups.filter(name="cid_user_manager").exists(): # if not request.user.groups.filter(name="cid_user_manager").exists():
@@ -1020,25 +1031,26 @@ class ExamViews(View, LoginRequiredMixin):
else: else:
statuses = exam.exam_user_status.all() statuses = exam.exam_user_status.all()
return render(request, "exam_user_status.html", {"exam": exam, "statuses": statuses}) return render(
request, "exam_user_status.html", {"exam": exam, "statuses": statuses}
)
#if not self.check_user_access(request.user, pk): # if not self.check_user_access(request.user, pk):
# raise PermissionDenied # raise PermissionDenied
#q, content_type = get_question_and_content_type(self.question_type) # q, content_type = get_question_and_content_type(self.question_type)
## Get active notes for type ## Get active notes for type
#statuses = ExamUserStatus.objects.filter( # statuses = ExamUserStatus.objects.filter(
# content_type=content_type, object_id__in=pk # content_type=content_type, object_id__in=pk
#) # )
#return statuses # return statuses
@method_decorator(login_required) @method_decorator(login_required)
def exam_json_edit(self, request, pk): def exam_json_edit(self, request, pk):
if request.method == "POST": if request.method == "POST":
if request.user.groups.filter(name="cid_user_manager").exists(): if request.user.groups.filter(name="cid_user_manager").exists():
# This may give more permissions than we actually want # This may give more permissions than we actually want
pass pass
@@ -1306,7 +1318,14 @@ class ExamViews(View, LoginRequiredMixin):
}, },
) )
def active_exams(self, request: HttpRequest, json: bool=True, based: bool=True, cid: int=None, passcode: str=None): def active_exams(
self,
request: HttpRequest,
json: bool = True,
based: bool = True,
cid: int = None,
passcode: str = None,
):
exams = self.Exam.objects.filter(archive=False) exams = self.Exam.objects.filter(archive=False)
active_exams = {"exams": []} active_exams = {"exams": []}
@@ -1321,7 +1340,9 @@ class ExamViews(View, LoginRequiredMixin):
exam: ExamBase exam: ExamBase
for exam in exams: for exam in exams:
if exam.active or self.check_user_access(request.user, exam.pk): if exam.active or self.check_user_access(request.user, exam.pk):
print(f"{exam.app_name=}, {exam.name=}, {cid=}, {passcode=}, {request.user=}") print(
f"{exam.app_name=}, {exam.name=}, {cid=}, {passcode=}, {request.user=}"
)
if exam.exam_mode and not exam.check_cid_user( if exam.exam_mode and not exam.check_cid_user(
cid, passcode, request=request, user_id=request.user.pk cid, passcode, request=request, user_id=request.user.pk
): ):
@@ -1333,7 +1354,9 @@ class ExamViews(View, LoginRequiredMixin):
else: else:
creation_time = "None" creation_time = "None"
url = request.build_absolute_uri(exam.get_json_url(cid=cid, passcode=passcode)) url = request.build_absolute_uri(
exam.get_json_url(cid=cid, passcode=passcode)
)
# hacky # hacky
if not based: if not based:
url = url + "/unbased" url = url + "/unbased"
@@ -1544,7 +1567,6 @@ class ExamViews(View, LoginRequiredMixin):
return JsonResponse({"success": True, "question_count": n}) return JsonResponse({"success": True, "question_count": n})
return JsonResponse({"success": False, "error": "Invalid data"}) return JsonResponse({"success": False, "error": "Invalid data"})
def exam_json_cid(self, request, pk, cid, passcode): def exam_json_cid(self, request, pk, cid, passcode):
return self.exam_json(request, pk, cid, passcode) return self.exam_json(request, pk, cid, passcode)
@@ -1578,7 +1600,9 @@ class ExamViews(View, LoginRequiredMixin):
cid_user = CidUser.objects.get(cid=cid) cid_user = CidUser.objects.get(cid=cid)
else: else:
cid_user = None cid_user = None
exam.exam_user_status.create(cid_user=cid_user, user_user=user, status="downloaded") exam.exam_user_status.create(
cid_user=cid_user, user_user=user, status="downloaded"
)
path = "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk) path = "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk)
url = "{0}{1}/exam/{2}.json".format(settings.MEDIA_URL, self.app_name, pk) url = "{0}{1}/exam/{2}.json".format(settings.MEDIA_URL, self.app_name, pk)
@@ -1629,6 +1653,14 @@ class ExamViews(View, LoginRequiredMixin):
if not exam.active and not self.check_user_access(request.user, pk): if not exam.active and not self.check_user_access(request.user, pk):
raise Http404("No available exam") raise Http404("No available exam")
# Check access for users
if request.user.is_anonymous:
user_id = None
else:
user_id = request.user.pk
if not exam.check_cid_user(cid, passcode, request, user_id):
raise Http404("No available exam")
time = datetime.now() time = datetime.now()
exam_json = exam.get_exam_json(based=False) exam_json = exam.get_exam_json(based=False)
@@ -1642,17 +1674,30 @@ class ExamViews(View, LoginRequiredMixin):
cid_user = CidUser.objects.get(cid=cid) cid_user = CidUser.objects.get(cid=cid)
else: else:
cid_user = None cid_user = None
exam.exam_user_status.create(cid_user=cid, user_user=user, status="downloaded", extra="unbased") exam.exam_user_status.create(
cid_user=cid, user_user=user, status="downloaded", extra="unbased"
)
return JsonResponse(exam_json) return JsonResponse(exam_json)
def exam_question_json(self, request, pk, sk): def exam_question_json_cid(self, request, pk, sk, cid, passcode):
return self.exam_question_json(request, pk, sk, cid, passcode)
def exam_question_json(self, request, pk, sk, cid=None, passcode=None):
question = get_object_or_404(self.Question, pk=sk) question = get_object_or_404(self.Question, pk=sk)
exam = get_object_or_404(self.Exam, pk=pk) exam = get_object_or_404(self.Exam, pk=pk)
if not exam.active and not self.check_user_access(request.user, pk): if not exam.active and not self.check_user_access(request.user, pk):
raise Http404("No available exam") raise Http404("No available exam")
# Check access for users
if request.user.is_anonymous:
user_id = None
else:
user_id = request.user.pk
if not exam.check_cid_user(cid, passcode, request, user_id):
raise Http404("No available exam")
if request.GET.get("_"): if request.GET.get("_"):
base_url = redirect("{}:question_json".format(self.app_name), pk=sk) base_url = redirect("{}:question_json".format(self.app_name), pk=sk)
query_string = urllib.parse.urlencode({"_": request.GET.get("_")}) query_string = urllib.parse.urlencode({"_": request.GET.get("_")})
@@ -1661,6 +1706,9 @@ class ExamViews(View, LoginRequiredMixin):
return redirect("{}:question_json".format(self.app_name), pk=sk) return redirect("{}:question_json".format(self.app_name), pk=sk)
def exam_question_json_unbased_cid(self, request, pk, sk, cid, passcode):
return self.exam_question_json_unbased(request, pk, sk, cid, passcode)
def exam_question_json_unbased(self, request, pk, sk): def exam_question_json_unbased(self, request, pk, sk):
question = get_object_or_404(self.Question, pk=sk) question = get_object_or_404(self.Question, pk=sk)
exam = get_object_or_404(self.Exam, pk=pk) exam = get_object_or_404(self.Exam, pk=pk)
@@ -1815,7 +1863,6 @@ class ExamViews(View, LoginRequiredMixin):
cached_scores = True cached_scores = True
valid_cid_users = set(exam.valid_cid_users.all().values_list("cid", flat=True)) valid_cid_users = set(exam.valid_cid_users.all().values_list("cid", flat=True))
valid_user_users = set(exam.valid_user_users.all().values_list("pk", flat=True)) valid_user_users = set(exam.valid_user_users.all().values_list("pk", flat=True))
@@ -2242,7 +2289,6 @@ class CidUserView(CidManagerRequiredMixin, SingleTableMixin, FilterView):
return context return context
@user_is_cid_user_manager @user_is_cid_user_manager
def cid_group_view(request): def cid_group_view(request):
groups = CidUserGroup.objects.filter(archive=False) groups = CidUserGroup.objects.filter(archive=False)
@@ -2253,6 +2299,7 @@ def cid_group_view(request):
{"groups": groups}, {"groups": groups},
) )
@user_is_cid_user_manager @user_is_cid_user_manager
def cid_group_view_detail(request, group_id): def cid_group_view_detail(request, group_id):
group = get_object_or_404(CidUserGroup, pk=group_id) group = get_object_or_404(CidUserGroup, pk=group_id)
@@ -2265,6 +2312,7 @@ def cid_group_view_detail(request, group_id):
{"group": group, "users": users, "group_type": "cid"}, {"group": group, "users": users, "group_type": "cid"},
) )
@user_is_cid_user_manager @user_is_cid_user_manager
def cid_group_view_all(request): def cid_group_view_all(request):
groups = CidUserGroup.objects.filter() groups = CidUserGroup.objects.filter()
@@ -2275,11 +2323,12 @@ def cid_group_view_all(request):
{"groups": groups, "view_all": True}, {"groups": groups, "view_all": True},
) )
@user_is_cid_user_manager @user_is_cid_user_manager
def user_group_view_detail(request, group_id): def user_group_view_detail(request, group_id):
group = get_object_or_404(UserUserGroup, pk=group_id) group = get_object_or_404(UserUserGroup, pk=group_id)
users = group.users.filter() # Filter inactive users? users = group.users.filter() # Filter inactive users?
return render( return render(
request, request,
@@ -2287,6 +2336,89 @@ def user_group_view_detail(request, group_id):
{"group": group, "users": users, "group_type": "user"}, {"group": group, "users": users, "group_type": "user"},
) )
@user_is_cid_user_manager
def users_bulk_delete_supervisors(request):
if "selection" in request.POST:
selected_users = request.POST.getlist("selection")
user_models = User.objects.filter(id__in=selected_users)
for u in user_models:
u.userprofile.supervisor = None
u.save()
modified_users = ",".join([user.username for user in user_models])
return HttpResponse(
f"Supervisors removed from {modified_users}. Refresh page to see update",
content_type="text/plain",
)
else:
return HttpResponse("No users selected", content_type="text/plain")
@user_is_cid_user_manager
def users_bulk_edit_grade(request):
if request.htmx.trigger == "bulk-edit-grade-button":
user_grades = UserGrades.objects.all()
html = "".join(
[
f"""<button class='change-grade-button' name='add-grade--{grade.id}'
hx-post="{reverse('generic:users_bulk_edit_grade')}"
hx-include="[name='selection']"
hx-confirm="This will modify grades of all selected users, are you sure you wish to continue?"
hx-target="#htmx-info"
>{grade.name}</button>"""
for grade in user_grades
]
)
# TODO: work out how to actually use hyperscript
html = (
html
+ "<button _='on click for el in .change-grade-button remove el end then remove me'>Cancel</button>"
)
return HttpResponse(html, content_type="text/html")
elif request.htmx.trigger_name.startswith("add-grade"):
selected_users = request.POST.getlist("selection")
if not selected_users:
return HttpResponse("No users selected", content_type="text/html")
user_models = User.objects.filter(id__in=selected_users)
# u: User
for u in user_models:
u.userprofile.grade_id = request.htmx.trigger_name.split("--")[-1]
u.save()
return HttpResponse("Grades update", content_type="text/html")
else:
return HttpResponse("Error", content_type="text/html")
@user_is_cid_user_manager
def users_bulk_delete_supervisors(request):
if "selection" in request.POST:
selected_users = request.POST.getlist("selection")
user_models = User.objects.filter(id__in=selected_users)
for u in user_models:
u.userprofile.supervisor = None
u.save()
modified_users = ",".join([user.username for user in user_models])
return HttpResponse(
f"Supervisors removed from {modified_users}. Refresh page to see update",
content_type="text/plain",
)
else:
return HttpResponse("No users selected", content_type="text/plain")
@user_is_cid_user_manager @user_is_cid_user_manager
def user_group_view(request): def user_group_view(request):
groups = UserUserGroup.objects.filter(archive=False) groups = UserUserGroup.objects.filter(archive=False)
@@ -2391,10 +2523,12 @@ def candidate_email_results(request, cid, resend=False):
def candidate_email_results_resend(request, cid, resend=True): def candidate_email_results_resend(request, cid, resend=True):
return candidate_email_results(request, cid, resend=True) return candidate_email_results(request, cid, resend=True)
@user_is_cid_user_manager @user_is_cid_user_manager
def create_cid_email(request): def create_cid_email(request):
pass pass
@user_is_cid_user_manager @user_is_cid_user_manager
def manage_cid_users(request): def manage_cid_users(request):
if request.method == "POST": if request.method == "POST":
@@ -2410,7 +2544,6 @@ def manage_cid_users(request):
emails = json.loads(request.POST.get("emails")) emails = json.loads(request.POST.get("emails"))
number_to_create = int(request.POST.get("number_to_create")) number_to_create = int(request.POST.get("number_to_create"))
add_group = request.POST.get("add_group") add_group = request.POST.get("add_group")
@@ -2513,13 +2646,15 @@ def manage_cid_users(request):
validate_email(email) validate_email(email)
except ValidationError as e: except ValidationError as e:
invalid_emails.append(f"Invalid email: {email}") invalid_emails.append(f"Invalid email: {email}")
print(f"Email list {email_list}") print(f"Email list {email_list}")
if not email_list: if not email_list:
return JsonResponse({"status": "fail", "details": "No valid emails"}) return JsonResponse({"status": "fail", "details": "No valid emails"})
if invalid_emails or not email_list: if invalid_emails or not email_list:
e = "<br/>".join(invalid_emails) e = "<br/>".join(invalid_emails)
return JsonResponse({"status": "fail", "details": f"Unable to create users<hr>{e}"}) return JsonResponse(
{"status": "fail", "details": f"Unable to create users<hr>{e}"}
)
for e in email_list: for e in email_list:
passcode = "".join(random.choices(string.ascii_uppercase, k=4)) passcode = "".join(random.choices(string.ascii_uppercase, k=4))
@@ -2578,16 +2713,18 @@ class CidUserUpdate(CidManagerRequiredMixin, UpdateView):
model = CidUser model = CidUser
form_class = CidUserForm form_class = CidUserForm
class CidUserExamUpdate(CidManagerRequiredMixin, UpdateView): class CidUserExamUpdate(CidManagerRequiredMixin, UpdateView):
model = CidUser model = CidUser
form_class = CidUserExamForm form_class = CidUserExamForm
template_name = "generic/ciduserexam_form.html" template_name = "generic/ciduserexam_form.html"
#def get_context_data(self, *args, **kwargs): # def get_context_data(self, *args, **kwargs):
# context = super().get_context_data(**kwargs) # context = super().get_context_data(**kwargs)
# context["test"] = "HELLO" # context["test"] = "HELLO"
# return context # return context
class CidUserGroupDelete(RevisionMixin, CidManagerRequiredMixin, DeleteView): class CidUserGroupDelete(RevisionMixin, CidManagerRequiredMixin, DeleteView):
model = CidUserGroup model = CidUserGroup
template_name = "confirm_delete.html" template_name = "confirm_delete.html"
@@ -2672,16 +2809,18 @@ class ExamDeleteBase(RevisionMixin, DeleteView):
def exam_inactive(request, context): def exam_inactive(request, context):
return render(request, "exam_inactive.html", context) return render(request, "exam_inactive.html", context)
#class UserUserCreate(CidManagerRequiredMixin, CreateView):
# class UserUserCreate(CidManagerRequiredMixin, CreateView):
# model = User # model = User
# form_class = UserUserForm # form_class = UserUserForm
# template_name: str = "generic/user_creation_form.html" # template_name: str = "generic/user_creation_form.html"
# #
# success_url = reverse_lazy("accounts_list") # success_url = reverse_lazy("accounts_list")
def create_user(request, context=None): def create_user(request, context=None):
# if this is a POST request we need to process the form data # if this is a POST request we need to process the form data
if request.method == 'POST': if request.method == "POST":
# create a form instance and populate it with data from the request: # create a form instance and populate it with data from the request:
form = UserUserForm(request.POST) form = UserUserForm(request.POST)
# check whether it's valid: # check whether it's valid:
@@ -2692,20 +2831,22 @@ def create_user(request, context=None):
"first_name": request.POST["first_name"], "first_name": request.POST["first_name"],
"last_name": request.POST["last_name"], "last_name": request.POST["last_name"],
"email": request.POST["username"], "email": request.POST["username"],
"password": secrets.token_hex(nbytes=16) "password": secrets.token_hex(nbytes=16),
} }
new_user = User.objects.create_user(**user_dict) new_user = User.objects.create_user(**user_dict)
except Exception as error: except Exception as error:
errors = f"Unable to create account: {error}" errors = f"Unable to create account: {error}"
return render(request, 'generic/user_creation_form.html', {'form': form, "errors": errors}) return render(
request,
"generic/user_creation_form.html",
{"form": form, "errors": errors},
)
try: try:
user_profile = UserProfile.objects.get(user=new_user) user_profile = UserProfile.objects.get(user=new_user)
user_profile.peninsula_trainee = True user_profile.peninsula_trainee = True
if request.POST["grade"]: if request.POST["grade"]:
grade = UserGrades.objects.get(pk=request.POST["grade"]) grade = UserGrades.objects.get(pk=request.POST["grade"])
@@ -2714,12 +2855,16 @@ def create_user(request, context=None):
if request.POST["supervisor"]: if request.POST["supervisor"]:
supervisor = Supervisor.objects.get(pk=request.POST["supervisor"]) supervisor = Supervisor.objects.get(pk=request.POST["supervisor"])
user_profile.supervisor = supervisor user_profile.supervisor = supervisor
user_profile.save() user_profile.save()
except Exception as error: except Exception as error:
errors = f"Unable to create account profile {error}" errors = f"Unable to create account profile {error}"
return render(request, 'generic/user_creation_form.html', {'form': form, "errors": errors}) return render(
request,
"generic/user_creation_form.html",
{"form": form, "errors": errors},
)
return HttpResponseRedirect(reverse_lazy("accounts_list")) return HttpResponseRedirect(reverse_lazy("accounts_list"))
return reverse_lazy("accounts_list") return reverse_lazy("accounts_list")
@@ -2728,7 +2873,8 @@ def create_user(request, context=None):
else: else:
form = UserUserForm() form = UserUserForm()
return render(request, 'generic/user_creation_form.html', {'form': form}) return render(request, "generic/user_creation_form.html", {"form": form})
class SupervisorDetail(CidManagerRequiredMixin, DetailView): class SupervisorDetail(CidManagerRequiredMixin, DetailView):
model = Supervisor model = Supervisor
@@ -2739,15 +2885,18 @@ class SupervisorDelete(CidManagerRequiredMixin, DeleteView):
template_name: str = "confirm_delete.html" template_name: str = "confirm_delete.html"
success_url = reverse_lazy("generic:supervisor") success_url = reverse_lazy("generic:supervisor")
class SupervisorUpdate(CidManagerRequiredMixin, UpdateView): class SupervisorUpdate(CidManagerRequiredMixin, UpdateView):
model = Supervisor model = Supervisor
form_class = SupervisorForm form_class = SupervisorForm
#success_url = reverse_lazy("generic:supervisor_detail", kwargs={'pk': self.pk}) # success_url = reverse_lazy("generic:supervisor_detail", kwargs={'pk': self.pk})
class SupervisorCreate(CidManagerRequiredMixin, CreateView): class SupervisorCreate(CidManagerRequiredMixin, CreateView):
model = Supervisor model = Supervisor
form_class = SupervisorForm form_class = SupervisorForm
#success_url = reverse_lazy("generic:supervisor_detail") # success_url = reverse_lazy("generic:supervisor_detail")
class SupervisorList(CidManagerRequiredMixin, ListView): class SupervisorList(CidManagerRequiredMixin, ListView):
model = Supervisor model = Supervisor