From 7996248f796c3c5cde1ba43610c73ed95f9096b7 Mon Sep 17 00:00:00 2001
From: mnymkr
Date: Fri, 12 Jul 2024 19:03:51 +0700
Subject: [PATCH 1/4] added changing student's program functionality
---
accounts/forms.py | 15 ++++++++++++
accounts/urls.py | 2 ++
accounts/views.py | 29 +++++++++++++++++++++-
templates/accounts/edit_program.html | 34 ++++++++++++++++++++++++++
templates/accounts/profile_single.html | 6 +++++
5 files changed, 85 insertions(+), 1 deletion(-)
create mode 100644 templates/accounts/edit_program.html
diff --git a/accounts/forms.py b/accounts/forms.py
index d006ee4..cc99e1f 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -337,6 +337,21 @@ class ProfileUpdateForm(UserChangeForm):
]
+class ProgramUpdateForm(UserChangeForm):
+ program = forms.ModelChoiceField(
+ queryset=Program.objects.all(),
+ widget=forms.Select(
+ attrs={"class": "browser-default custom-select form-control"}
+ ),
+ label="Program",
+ )
+
+ class Meta:
+ model = Student
+ fields = [
+ "program"
+ ]
+
class EmailValidationOnForgotPassword(PasswordResetForm):
def clean_email(self):
email = self.cleaned_data["email"]
diff --git a/accounts/urls.py b/accounts/urls.py
index fd0737d..16dbe5a 100644
--- a/accounts/urls.py
+++ b/accounts/urls.py
@@ -22,6 +22,7 @@ from .views import (
student_add_view,
edit_student,
delete_student,
+ edit_program,
ParentAdd,
validate_username,
register,
@@ -47,6 +48,7 @@ urlpatterns = [
path("student/add/", student_add_view, name="add_student"),
path("student//edit/", edit_student, name="student_edit"),
path("students//delete/", delete_student, name="student_delete"),
+ path("edit_program//", edit_program, name="student_program_edit"),
path("parents/add/", ParentAdd.as_view(), name="add_parent"),
path("ajax/validate-username/", validate_username, name="validate_username"),
path("register/", register, name="register"),
diff --git a/accounts/views.py b/accounts/views.py
index 47fbead..c506498 100644
--- a/accounts/views.py
+++ b/accounts/views.py
@@ -12,7 +12,7 @@ from core.models import Session, Semester
from course.models import Course
from result.models import TakenCourse
from .decorators import admin_required
-from .forms import StaffAddForm, StudentAddForm, ProfileUpdateForm, ParentAddForm
+from .forms import StaffAddForm, StudentAddForm, ProfileUpdateForm, ParentAddForm, ProgramUpdateForm
from .models import User, Student, Parent
from .filters import LecturerFilter, StudentFilter
@@ -477,6 +477,33 @@ def delete_student(request, pk):
messages.success(request, "Student has been deleted.")
return redirect("student_list")
+@login_required
+@admin_required
+def edit_program(request, pk):
+
+ instance = get_object_or_404(Student, student_id=pk)
+ user = get_object_or_404(User, pk=pk)
+ if request.method == "POST":
+ form = ProgramUpdateForm(request.POST, request.FILES, instance=instance)
+ full_name = user.get_full_name
+ if form.is_valid():
+ form.save()
+ messages.success(request, message=full_name + " has been updated.")
+ url = "/accounts/profile/" + user.id.__str__() + "/detail/" # Botched job, must optimize
+ return redirect(to=url)
+ else:
+ messages.error(request, "Please correct the error(s) below.")
+ else:
+ form = ProgramUpdateForm(instance=instance)
+ return render(
+ request,
+ "accounts/edit_program.html",
+ context={
+ "title": "Edit-program",
+ "form": form
+ },
+ )
+
# ########################################################
diff --git a/templates/accounts/edit_program.html b/templates/accounts/edit_program.html
new file mode 100644
index 0000000..e45d193
--- /dev/null
+++ b/templates/accounts/edit_program.html
@@ -0,0 +1,34 @@
+{% extends 'base.html' %}
+{% block title %}{{ title }} | Learning management system{% endblock title %}
+{% load crispy_forms_tags %}
+{% load static %}
+
+{% block content %}
+
+
+
+ Home
+ Students
+ Update
+
+
+
+ Student Program Update Form
+
+{% include 'snippets/messages.html' %}
+
+
+{% endblock content %}
diff --git a/templates/accounts/profile_single.html b/templates/accounts/profile_single.html
index f3030b8..32a76d6 100644
--- a/templates/accounts/profile_single.html
+++ b/templates/accounts/profile_single.html
@@ -38,6 +38,11 @@
Edit Profile
+
+ {# had to name out of convention because it clashes with 'edit_[whatever]program', which directs to 'program/[id]/edit/ #}
+
+ Change Program
+
{% endif %}
{% if user.is_lecturer %}
@@ -93,6 +98,7 @@
School: Hawas Preparatory School
Level: {{ level.level }}
+
Program: {{ student.program }}
{% endif %}
From bf57019fda0716e2b8cf92d0b262a760f63924ea Mon Sep 17 00:00:00 2001
From: mnymkr
Date: Fri, 12 Jul 2024 19:17:40 +0700
Subject: [PATCH 2/4] added the option to change a student's program in student
update form
---
accounts/forms.py | 8 ++++++++
accounts/views.py | 5 +++++
templates/accounts/edit_student.html | 1 +
templates/accounts/profile_single.html | 7 +++----
4 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/accounts/forms.py b/accounts/forms.py
index cc99e1f..a6ed970 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -324,6 +324,14 @@ class ProfileUpdateForm(UserChangeForm):
label="Address / city",
)
+ program = forms.ModelChoiceField(
+ queryset=Program.objects.all(),
+ widget=forms.Select(
+ attrs={"class": "browser-default custom-select form-control"}
+ ),
+ label="Program",
+ )
+
class Meta:
model = User
fields = [
diff --git a/accounts/views.py b/accounts/views.py
index c506498..2da75c6 100644
--- a/accounts/views.py
+++ b/accounts/views.py
@@ -420,6 +420,10 @@ def edit_student(request, pk):
if form.is_valid():
form.save()
+ student = Student.objects.get(student_id=instance.id)
+ student.program = form.cleaned_data["program"]
+ student.save()
+
messages.success(request, ("Student " + full_name + " has been updated."))
return redirect("student_list")
else:
@@ -477,6 +481,7 @@ def delete_student(request, pk):
messages.success(request, "Student has been deleted.")
return redirect("student_list")
+# REDUNDANT
@login_required
@admin_required
def edit_program(request, pk):
diff --git a/templates/accounts/edit_student.html b/templates/accounts/edit_student.html
index 8a56495..25b7169 100644
--- a/templates/accounts/edit_student.html
+++ b/templates/accounts/edit_student.html
@@ -30,6 +30,7 @@
{{ form.gender|as_crispy_field }}
{{ form.phone|as_crispy_field }}
{{ form.address|as_crispy_field }}
+ {{ form.program|as_crispy_field }}
diff --git a/templates/accounts/profile_single.html b/templates/accounts/profile_single.html
index 32a76d6..cc38a78 100644
--- a/templates/accounts/profile_single.html
+++ b/templates/accounts/profile_single.html
@@ -38,11 +38,10 @@
Edit Profile
-
{# had to name out of convention because it clashes with 'edit_[whatever]program', which directs to 'program/[id]/edit/ #}
-
- Change Program
-
+{# #}
+{# Change Program #}
+{# #}
{% endif %}
{% if user.is_lecturer %}
From 66f902b68030749daf6e490d63c9494cb72f79dd Mon Sep 17 00:00:00 2001
From: Hoannhi
Date: Sun, 14 Jul 2024 21:30:30 +0700
Subject: [PATCH 3/4] Change student email template to show password and ID.
---
.idea/.gitignore | 8 ++++++++
config/settings.py | 1 +
.../accounts/email/new_student_account_confirmation.html | 4 ++--
3 files changed, 11 insertions(+), 2 deletions(-)
create mode 100644 .idea/.gitignore
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/config/settings.py b/config/settings.py
index d9df0c7..f841c49 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -199,6 +199,7 @@ EMAIL_USE_TLS = True
EMAIL_HOST_USER = config("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = config("EMAIL_HOST_PASSWORD")
EMAIL_FROM_ADDRESS = config("EMAIL_FROM_ADDRESS")
+EMAIL_USE_SSL = False
# crispy config
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
diff --git a/templates/accounts/email/new_student_account_confirmation.html b/templates/accounts/email/new_student_account_confirmation.html
index 9e35d9d..c04c6db 100755
--- a/templates/accounts/email/new_student_account_confirmation.html
+++ b/templates/accounts/email/new_student_account_confirmation.html
@@ -268,8 +268,8 @@
Login credentials for your DJ LMS account:
- ID: {user.username}
- Your password: {password}
+ ID: {{ user.username }}
+ Your password: {{ password }}
To secure your account be sure to change your password.
From 9d132440f9309e90335bfa318e602d3e5fde72cf Mon Sep 17 00:00:00 2001
From: Adil Mohak
Date: Tue, 30 Jul 2024 17:37:03 +0300
Subject: [PATCH 4/4] Student program edit form and other minor updates
---
accounts/forms.py | 13 +--
accounts/urls.py | 22 +++--
accounts/views.py | 93 ++++++++++---------
templates/accounts/edit_student.html | 1 -
...program.html => edit_student_program.html} | 2 +
.../new_lecturer_account_confirmation.html | 6 +-
templates/accounts/profile.html | 4 +-
templates/accounts/profile_single.html | 17 ++--
8 files changed, 80 insertions(+), 78 deletions(-)
rename templates/accounts/{edit_program.html => edit_student_program.html} (87%)
diff --git a/accounts/forms.py b/accounts/forms.py
index a6ed970..63a5ff9 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -324,14 +324,6 @@ class ProfileUpdateForm(UserChangeForm):
label="Address / city",
)
- program = forms.ModelChoiceField(
- queryset=Program.objects.all(),
- widget=forms.Select(
- attrs={"class": "browser-default custom-select form-control"}
- ),
- label="Program",
- )
-
class Meta:
model = User
fields = [
@@ -356,9 +348,8 @@ class ProgramUpdateForm(UserChangeForm):
class Meta:
model = Student
- fields = [
- "program"
- ]
+ fields = ["program"]
+
class EmailValidationOnForgotPassword(PasswordResetForm):
def clean_email(self):
diff --git a/accounts/urls.py b/accounts/urls.py
index 16dbe5a..3042276 100644
--- a/accounts/urls.py
+++ b/accounts/urls.py
@@ -22,12 +22,12 @@ from .views import (
student_add_view,
edit_student,
delete_student,
- edit_program,
+ edit_student_program,
ParentAdd,
validate_username,
register,
- render_lecturer_pdf_list, #new
- render_student_pdf_list #new
+ render_lecturer_pdf_list, # new
+ render_student_pdf_list, # new
)
# from .forms import EmailValidationOnForgotPassword
@@ -48,13 +48,21 @@ urlpatterns = [
path("student/add/", student_add_view, name="add_student"),
path("student//edit/", edit_student, name="student_edit"),
path("students//delete/", delete_student, name="student_delete"),
- path("edit_program//", edit_program, name="student_program_edit"),
+ path(
+ "edit_student_program//",
+ edit_student_program,
+ name="student_program_edit",
+ ),
path("parents/add/", ParentAdd.as_view(), name="add_parent"),
path("ajax/validate-username/", validate_username, name="validate_username"),
path("register/", register, name="register"),
- #paths to pdf
- path("create_lecturers_pdf_list/", render_lecturer_pdf_list, name="lecturer_list_pdf"), #new
- path("create_students_pdf_list/", render_student_pdf_list, name="student_list_pdf"), #new
+ # paths to pdf
+ path(
+ "create_lecturers_pdf_list/", render_lecturer_pdf_list, name="lecturer_list_pdf"
+ ), # new
+ path(
+ "create_students_pdf_list/", render_student_pdf_list, name="student_list_pdf"
+ ), # new
# path('add-student/', StudentAddView.as_view(), name='add_student'),
# path('programs/course/delete//', course_delete, name='delete_course'),
# Setting urls
diff --git a/accounts/views.py b/accounts/views.py
index 2da75c6..ac60678 100644
--- a/accounts/views.py
+++ b/accounts/views.py
@@ -12,15 +12,24 @@ from core.models import Session, Semester
from course.models import Course
from result.models import TakenCourse
from .decorators import admin_required
-from .forms import StaffAddForm, StudentAddForm, ProfileUpdateForm, ParentAddForm, ProgramUpdateForm
+from .forms import (
+ StaffAddForm,
+ StudentAddForm,
+ ProfileUpdateForm,
+ ParentAddForm,
+ ProgramUpdateForm,
+)
from .models import User, Student, Parent
from .filters import LecturerFilter, StudentFilter
-#to generate pdf from template we need the following
+# to generate pdf from template we need the following
from django.http import HttpResponse
-from django.template.loader import get_template # to get template which render as pdf
+from django.template.loader import get_template # to get template which render as pdf
from xhtml2pdf import pisa
-from django.template.loader import render_to_string #to render a template into a string
+from django.template.loader import (
+ render_to_string,
+) # to render a template into a string
+
def validate_username(request):
username = request.GET.get("username", None)
@@ -96,20 +105,18 @@ def profile(request):
},
)
-#function that generate pdf by taking Django template and its context,
+
+# function that generate pdf by taking Django template and its context,
def render_to_pdf(template_name, context):
"""Renders a given template to PDF format."""
- response = HttpResponse(content_type='application/pdf')
- response['Content-Disposition'] = 'filename="profile.pdf"' # Set default filename
+ response = HttpResponse(content_type="application/pdf")
+ response["Content-Disposition"] = 'filename="profile.pdf"' # Set default filename
template = render_to_string(template_name, context)
- pdf = pisa.CreatePDF(
- template,
- dest=response
- )
+ pdf = pisa.CreatePDF(template, dest=response)
if pdf.err:
- return HttpResponse('We had some problems generating the PDF')
-
+ return HttpResponse("We had some problems generating the PDF")
+
return response
@@ -131,7 +138,7 @@ def profile_single(request, id):
pass the context dictionary built for the specific user type
(lecturer, student, or superuser) to the render_to_pdf function.
"""
- if request.GET.get('download_pdf'):
+ if request.GET.get("download_pdf"):
if user.is_lecturer:
courses = Course.objects.filter(allocated_course__lecturer__pk=id).filter(
semester=current_semester
@@ -339,26 +346,26 @@ class LecturerFilterView(FilterView):
return context
-#lecturers list pdf
+# lecturers list pdf
def render_lecturer_pdf_list(request):
lecturers = User.objects.filter(is_lecturer=True)
- template_path = 'pdf/lecturer_list.html'
- context = {'lecturers':lecturers}
- response = HttpResponse(content_type='application/pdf') # convert the response to pdf
- response['Content-Disposition'] = 'filename="lecturers_list.pdf"'
+ template_path = "pdf/lecturer_list.html"
+ context = {"lecturers": lecturers}
+ response = HttpResponse(
+ content_type="application/pdf"
+ ) # convert the response to pdf
+ response["Content-Disposition"] = 'filename="lecturers_list.pdf"'
# find the template and render it.
template = get_template(template_path)
html = template.render(context)
# create a pdf
- pisa_status = pisa.CreatePDF(
- html, dest=response)
+ pisa_status = pisa.CreatePDF(html, dest=response)
# if error then show some funny view
if pisa_status.err:
- return HttpResponse('We had some errors ' + html + ' ')
+ return HttpResponse("We had some errors " + html + " ")
return response
-
-
+
# @login_required
# @lecturer_required
# def delete_staff(request, pk):
@@ -420,10 +427,6 @@ def edit_student(request, pk):
if form.is_valid():
form.save()
- student = Student.objects.get(student_id=instance.id)
- student.program = form.cleaned_data["program"]
- student.save()
-
messages.success(request, ("Student " + full_name + " has been updated."))
return redirect("student_list")
else:
@@ -453,22 +456,23 @@ class StudentListView(FilterView):
return context
-#student list pdf
+# student list pdf
def render_student_pdf_list(request):
students = Student.objects.all()
- template_path = 'pdf/student_list.html'
- context = {'students':students}
- response = HttpResponse(content_type='application/pdf') # convert the response to pdf
- response['Content-Disposition'] = 'filename="students_list.pdf"'
+ template_path = "pdf/student_list.html"
+ context = {"students": students}
+ response = HttpResponse(
+ content_type="application/pdf"
+ ) # convert the response to pdf
+ response["Content-Disposition"] = 'filename="students_list.pdf"'
# find the template and render it.
template = get_template(template_path)
html = template.render(context)
# create a pdf
- pisa_status = pisa.CreatePDF(
- html, dest=response)
+ pisa_status = pisa.CreatePDF(html, dest=response)
# if error then show some funny view
if pisa_status.err:
- return HttpResponse('We had some errors ' + html + ' ')
+ return HttpResponse("We had some errors " + html + " ")
return response
@@ -481,10 +485,10 @@ def delete_student(request, pk):
messages.success(request, "Student has been deleted.")
return redirect("student_list")
-# REDUNDANT
+
@login_required
@admin_required
-def edit_program(request, pk):
+def edit_student_program(request, pk):
instance = get_object_or_404(Student, student_id=pk)
user = get_object_or_404(User, pk=pk)
@@ -493,8 +497,10 @@ def edit_program(request, pk):
full_name = user.get_full_name
if form.is_valid():
form.save()
- messages.success(request, message=full_name + " has been updated.")
- url = "/accounts/profile/" + user.id.__str__() + "/detail/" # Botched job, must optimize
+ messages.success(request, message=full_name + " program has been updated.")
+ url = (
+ "/accounts/profile/" + user.id.__str__() + "/detail/"
+ ) # Botched job, must optimize
return redirect(to=url)
else:
messages.error(request, "Please correct the error(s) below.")
@@ -502,11 +508,8 @@ def edit_program(request, pk):
form = ProgramUpdateForm(instance=instance)
return render(
request,
- "accounts/edit_program.html",
- context={
- "title": "Edit-program",
- "form": form
- },
+ "accounts/edit_student_program.html",
+ context={"title": "Edit-program", "form": form, "student": instance},
)
diff --git a/templates/accounts/edit_student.html b/templates/accounts/edit_student.html
index 25b7169..8a56495 100644
--- a/templates/accounts/edit_student.html
+++ b/templates/accounts/edit_student.html
@@ -30,7 +30,6 @@
{{ form.gender|as_crispy_field }}
{{ form.phone|as_crispy_field }}
{{ form.address|as_crispy_field }}
- {{ form.program|as_crispy_field }}
diff --git a/templates/accounts/edit_program.html b/templates/accounts/edit_student_program.html
similarity index 87%
rename from templates/accounts/edit_program.html
rename to templates/accounts/edit_student_program.html
index e45d193..6b7c678 100644
--- a/templates/accounts/edit_program.html
+++ b/templates/accounts/edit_student_program.html
@@ -24,6 +24,8 @@
Program
+
Change {{ student.student.get_full_name }}'s program
+
{{ form.program|as_crispy_field }}
diff --git a/templates/accounts/email/new_lecturer_account_confirmation.html b/templates/accounts/email/new_lecturer_account_confirmation.html
index 1d30167..5e21e27 100755
--- a/templates/accounts/email/new_lecturer_account_confirmation.html
+++ b/templates/accounts/email/new_lecturer_account_confirmation.html
@@ -261,15 +261,15 @@
🚀 Confirm your account
Dear {{ user.get_full_name }} ,
- A new lecturer account with ID of {user.username} has been
+ A new lecturer account with ID of {{ user.username }} has been
created for you.
You're receiving this e-mail because the Dj-LMS admin has given your
e-mail address to register an account on djlms.com.
Login credentials for your DJ LMS account:
- ID: {user.username}
- Your password: {password}
+ ID: {{ user.username }}
+ Your password: {{ password }}
To secure your account be sure to change your password.
diff --git a/templates/accounts/profile.html b/templates/accounts/profile.html
index 55532f4..cd5266f 100644
--- a/templates/accounts/profile.html
+++ b/templates/accounts/profile.html
@@ -32,9 +32,9 @@
-
+
Edit Profile
-
+
Change password
diff --git a/templates/accounts/profile_single.html b/templates/accounts/profile_single.html
index cc38a78..de0cc93 100644
--- a/templates/accounts/profile_single.html
+++ b/templates/accounts/profile_single.html
@@ -33,19 +33,18 @@
{% if request.user.is_superuser %}
-