Merge branch 'mnymkr-edit-program'

This commit is contained in:
Adil Mohak 2024-07-30 17:39:14 +03:00
commit 28ba3f6ecc
10 changed files with 157 additions and 49 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@ -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

View File

@ -337,6 +337,20 @@ 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): class EmailValidationOnForgotPassword(PasswordResetForm):
def clean_email(self): def clean_email(self):
email = self.cleaned_data["email"] email = self.cleaned_data["email"]

View File

@ -22,11 +22,12 @@ from .views import (
student_add_view, student_add_view,
edit_student, edit_student,
delete_student, delete_student,
edit_student_program,
ParentAdd, ParentAdd,
validate_username, validate_username,
register, register,
render_lecturer_pdf_list, #new render_lecturer_pdf_list, # new
render_student_pdf_list #new render_student_pdf_list, # new
) )
# from .forms import EmailValidationOnForgotPassword # from .forms import EmailValidationOnForgotPassword
@ -47,12 +48,21 @@ urlpatterns = [
path("student/add/", student_add_view, name="add_student"), path("student/add/", student_add_view, name="add_student"),
path("student/<int:pk>/edit/", edit_student, name="student_edit"), path("student/<int:pk>/edit/", edit_student, name="student_edit"),
path("students/<int:pk>/delete/", delete_student, name="student_delete"), path("students/<int:pk>/delete/", delete_student, name="student_delete"),
path(
"edit_student_program/<int:pk>/",
edit_student_program,
name="student_program_edit",
),
path("parents/add/", ParentAdd.as_view(), name="add_parent"), path("parents/add/", ParentAdd.as_view(), name="add_parent"),
path("ajax/validate-username/", validate_username, name="validate_username"), path("ajax/validate-username/", validate_username, name="validate_username"),
path("register/", register, name="register"), path("register/", register, name="register"),
#paths to pdf # paths to pdf
path("create_lecturers_pdf_list/", render_lecturer_pdf_list, name="lecturer_list_pdf"), #new path(
path("create_students_pdf_list/", render_student_pdf_list, name="student_list_pdf"), #new "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('add-student/', StudentAddView.as_view(), name='add_student'),
# path('programs/course/delete/<int:pk>/', course_delete, name='delete_course'), # path('programs/course/delete/<int:pk>/', course_delete, name='delete_course'),
# Setting urls # Setting urls

View File

@ -12,15 +12,24 @@ from core.models import Session, Semester
from course.models import Course from course.models import Course
from result.models import TakenCourse from result.models import TakenCourse
from .decorators import admin_required 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 .models import User, Student, Parent
from .filters import LecturerFilter, StudentFilter 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.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 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): def validate_username(request):
username = request.GET.get("username", None) 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): def render_to_pdf(template_name, context):
"""Renders a given template to PDF format.""" """Renders a given template to PDF format."""
response = HttpResponse(content_type='application/pdf') response = HttpResponse(content_type="application/pdf")
response['Content-Disposition'] = 'filename="profile.pdf"' # Set default filename response["Content-Disposition"] = 'filename="profile.pdf"' # Set default filename
template = render_to_string(template_name, context) template = render_to_string(template_name, context)
pdf = pisa.CreatePDF( pdf = pisa.CreatePDF(template, dest=response)
template,
dest=response
)
if pdf.err: if pdf.err:
return HttpResponse('We had some problems generating the PDF') return HttpResponse("We had some problems generating the PDF")
return response return response
@ -131,7 +138,7 @@ def profile_single(request, id):
pass the context dictionary built for the specific user type pass the context dictionary built for the specific user type
(lecturer, student, or superuser) to the render_to_pdf function. (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: if user.is_lecturer:
courses = Course.objects.filter(allocated_course__lecturer__pk=id).filter( courses = Course.objects.filter(allocated_course__lecturer__pk=id).filter(
semester=current_semester semester=current_semester
@ -339,26 +346,26 @@ class LecturerFilterView(FilterView):
return context return context
#lecturers list pdf # lecturers list pdf
def render_lecturer_pdf_list(request): def render_lecturer_pdf_list(request):
lecturers = User.objects.filter(is_lecturer=True) lecturers = User.objects.filter(is_lecturer=True)
template_path = 'pdf/lecturer_list.html' template_path = "pdf/lecturer_list.html"
context = {'lecturers':lecturers} context = {"lecturers": lecturers}
response = HttpResponse(content_type='application/pdf') # convert the response to pdf response = HttpResponse(
response['Content-Disposition'] = 'filename="lecturers_list.pdf"' content_type="application/pdf"
) # convert the response to pdf
response["Content-Disposition"] = 'filename="lecturers_list.pdf"'
# find the template and render it. # find the template and render it.
template = get_template(template_path) template = get_template(template_path)
html = template.render(context) html = template.render(context)
# create a pdf # create a pdf
pisa_status = pisa.CreatePDF( pisa_status = pisa.CreatePDF(html, dest=response)
html, dest=response)
# if error then show some funny view # if error then show some funny view
if pisa_status.err: if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>') return HttpResponse("We had some errors <pre>" + html + "</pre>")
return response return response
# @login_required # @login_required
# @lecturer_required # @lecturer_required
# def delete_staff(request, pk): # def delete_staff(request, pk):
@ -449,22 +456,23 @@ class StudentListView(FilterView):
return context return context
#student list pdf # student list pdf
def render_student_pdf_list(request): def render_student_pdf_list(request):
students = Student.objects.all() students = Student.objects.all()
template_path = 'pdf/student_list.html' template_path = "pdf/student_list.html"
context = {'students':students} context = {"students": students}
response = HttpResponse(content_type='application/pdf') # convert the response to pdf response = HttpResponse(
response['Content-Disposition'] = 'filename="students_list.pdf"' content_type="application/pdf"
) # convert the response to pdf
response["Content-Disposition"] = 'filename="students_list.pdf"'
# find the template and render it. # find the template and render it.
template = get_template(template_path) template = get_template(template_path)
html = template.render(context) html = template.render(context)
# create a pdf # create a pdf
pisa_status = pisa.CreatePDF( pisa_status = pisa.CreatePDF(html, dest=response)
html, dest=response)
# if error then show some funny view # if error then show some funny view
if pisa_status.err: if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>') return HttpResponse("We had some errors <pre>" + html + "</pre>")
return response return response
@ -478,6 +486,33 @@ def delete_student(request, pk):
return redirect("student_list") return redirect("student_list")
@login_required
@admin_required
def edit_student_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 + " 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.")
else:
form = ProgramUpdateForm(instance=instance)
return render(
request,
"accounts/edit_student_program.html",
context={"title": "Edit-program", "form": form, "student": instance},
)
# ######################################################## # ########################################################

View File

@ -199,6 +199,7 @@ EMAIL_USE_TLS = config("EMAIL_USE_TLS", default=True, cast=bool)
EMAIL_HOST_USER = config("EMAIL_HOST_USER") EMAIL_HOST_USER = config("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = config("EMAIL_HOST_PASSWORD") EMAIL_HOST_PASSWORD = config("EMAIL_HOST_PASSWORD")
EMAIL_FROM_ADDRESS = config("EMAIL_FROM_ADDRESS") EMAIL_FROM_ADDRESS = config("EMAIL_FROM_ADDRESS")
EMAIL_USE_SSL = False
# crispy config # crispy config
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"

View File

@ -0,0 +1,36 @@
{% extends 'base.html' %}
{% block title %}{{ title }} | Learning management system{% endblock title %}
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
<nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'student_list' %}">Students</a></li>
<li class="breadcrumb-item active" aria-current="page">Update</li>
</ol>
</nav>
<h4 class="fw-bold mb-3"><i class="fas fa-cog me-2"></i>Student Program Update Form</h4>
{% include 'snippets/messages.html' %}
<form action="" method="POST" enctype="multipart/form-data">{% csrf_token %}
<div class="row mb-3">
<div class="col-md-6">
<div class="card">
<p class="form-title">Program</p>
<div class="card-body">
<p>Change <a href="{{ student.student.get_absolute_url }}">{{ student.student.get_full_name }}'s</a> program</p>
<hr>
{{ form.program|as_crispy_field }}
</div>
</div>
</div>
</div>
<input class="btn btn-primary" type="submit" value="Save">
</form>
{% endblock content %}

View File

@ -261,15 +261,15 @@
<h1 class="mb-5">🚀 Confirm your account</h1> <h1 class="mb-5">🚀 Confirm your account</h1>
<h4>Dear <b>{{ user.get_full_name }}</b>,</h4> <h4>Dear <b>{{ user.get_full_name }}</b>,</h4>
<p> <p>
A new lecturer account with ID of <b>{user.username}</b> has been A new lecturer account with ID of <b>{{ user.username }}</b> has been
created for you. <br /> created for you. <br />
You're receiving this e-mail because the Dj-LMS admin has given your You're receiving this e-mail because the Dj-LMS admin has given your
e-mail address to register an account on djlms.com. <br /> e-mail address to register an account on djlms.com. <br />
</p> </p>
<h5>Login credentials for your DJ LMS account:</h5> <h5>Login credentials for your DJ LMS account:</h5>
<ul> <ul>
<li>ID: {user.username}</li> <li>ID: {{ user.username }}</li>
<li>Your password: {password}</li> <li>Your password: {{ password }}</li>
</ul> </ul>
<p>To secure your account be sure to change your password.</p> <p>To secure your account be sure to change your password.</p>
<p> <p>

View File

@ -268,8 +268,8 @@
</p> </p>
<h5>Login credentials for your DJ LMS account:</h5> <h5>Login credentials for your DJ LMS account:</h5>
<ul> <ul>
<li>ID: {user.username}</li> <li>ID: {{ user.username }}</li>
<li>Your password: {password}</li> <li>Your password: {{ password }}</li>
</ul> </ul>
<p>To secure your account be sure to change your password.</p> <p>To secure your account be sure to change your password.</p>
<p> <p>

View File

@ -32,9 +32,9 @@
</ul> </ul>
</div> </div>
<hr> <hr>
<a class="mb-2" href="{% url 'edit_profile' %}"><i class="fas fa-user-edit"></i> <a class="mb-2" href="{% url 'edit_profile' %}"><i class="fas fa-user-edit unstyled"></i>
<span class="mobile-hide">Edit Profile</span></a> <span class="mobile-hide">Edit Profile</span></a>
<a href="{% url 'change_password' %}"><i class="fas fa-lock"></i><span class="mobile-hide"> <a href="{% url 'change_password' %}"><i class="fas fa-lock unstyled"></i><span class="mobile-hide">
Change password</span></a> Change password</span></a>
</div> </div>
</div> </div>

View File

@ -33,15 +33,18 @@
</div> </div>
<hr> <hr>
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<div class="btn-flex"> <div class="d-flex flex-column">
{% if user.is_student %} {% if user.is_student %}
<a class="edit-btn" href="{% url 'student_edit' pk=user.id %}"> <a href="{% url 'student_edit' pk=user.id %}">
<i class="fas fa-user-edit"></i><span class="mobile-hide">Edit Profile</span> <i class="fas fa-user-edit unstyled"></i><span class="mobile-hide">Edit Profile</span>
</a>
<a href="{% url 'student_program_edit' user.id %}">
<i class="fas fa-pen-to-square unstyled"></i><span class="mobile-hide">Change Program</span>
</a> </a>
{% endif %} {% endif %}
{% if user.is_lecturer %} {% if user.is_lecturer %}
<a class="edit-btn" href="{% url 'staff_edit' pk=user.id %}"> <a href="{% url 'staff_edit' pk=user.id %}">
<i class="fas fa-user-edit"></i><span class="mobile-hide">Edit Profile</span> <i class="fas fa-user-edit unstyled"></i><span class="mobile-hide">Edit Profile</span>
</a> </a>
{% endif %} {% endif %}
</div> </div>
@ -93,6 +96,7 @@
<div class="dashboard-description"> <div class="dashboard-description">
<p><strong>School: </strong>Hawas Preparatory School</p> <p><strong>School: </strong>Hawas Preparatory School</p>
<p><strong>Level: </strong>{{ level.level }}</p> <p><strong>Level: </strong>{{ level.level }}</p>
<p><strong>Program: </strong>{{ student.program }}</p>
</div> </div>
{% endif %} {% endif %}