Merge pull request #40 from y938/feature/export_data

Adding the ability to download a PDF list of students and lecturers.
This commit is contained in:
Adil Mohak 2024-04-03 09:52:08 +03:00 committed by GitHub
commit 8ecbc1c9d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 190 additions and 1 deletions

View File

@ -25,6 +25,8 @@ from .views import (
ParentAdd, ParentAdd,
validate_username, validate_username,
register, register,
render_lecturer_pdf_list, #new
render_student_pdf_list #new
) )
# from .forms import EmailValidationOnForgotPassword # from .forms import EmailValidationOnForgotPassword
@ -48,6 +50,9 @@ urlpatterns = [
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
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('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

@ -16,6 +16,10 @@ from .forms import StaffAddForm, StudentAddForm, ProfileUpdateForm, ParentAddFor
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
from django.http import HttpResponse
from django.template.loader import get_template # to get template which render as pdf
from xhtml2pdf import pisa
def validate_username(request): def validate_username(request):
username = request.GET.get("username", None) username = request.GET.get("username", None)
@ -275,6 +279,26 @@ class LecturerFilterView(FilterView):
return context return context
#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"'
# 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)
# if error then show some funny view
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return response
# @login_required # @login_required
# @lecturer_required # @lecturer_required
# def delete_staff(request, pk): # def delete_staff(request, pk):
@ -365,6 +389,25 @@ class StudentListView(FilterView):
return context return context
#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"'
# 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)
# if error then show some funny view
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return response
@login_required @login_required
@admin_required @admin_required
def delete_student(request, pk): def delete_student(request, pk):

View File

@ -1,5 +1,5 @@
pytz==2022.7 # https://github.com/stub42/pytz pytz==2022.7 # https://github.com/stub42/pytz
Pillow==9.3.0 # https://github.com/python-pillow/Pillow Pillow==9.3.0 # https://github.com/python-pillow/Pillow
whitenoise==6.2.0 # https://github.com/evansd/whitenoise whitenoise==6.2.0 # https://github.com/evansd/whitenoise
# Django # Django
@ -16,6 +16,7 @@ django-cors-headers==3.13.0 # https://github.com/adamchainz/django-cors-headers
# PDF generator # PDF generator
reportlab==4.0.4 reportlab==4.0.4
xhtml2pdf==0.2.15
# Customize django admin # Customize django admin
django-jet-reboot==1.3.5 django-jet-reboot==1.3.5

View File

@ -13,6 +13,7 @@
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<div class="manage-wrap"> <div class="manage-wrap">
<a class="btn btn-primary" href="{% url 'add_lecturer' %}"><i class="fas fa-plus"></i>Add Lecturer</a> <a class="btn btn-primary" href="{% url 'add_lecturer' %}"><i class="fas fa-plus"></i>Add Lecturer</a>
<a class="btn btn-primary" target="_blank" href="{% url 'lecturer_list_pdf' %}"><i class="fas fa-download"></i> Download pdf</a><!--new-->
</div> </div>
{% endif %} {% endif %}

View File

@ -16,6 +16,7 @@
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<div class="manage-wrap"> <div class="manage-wrap">
<a class="btn btn-sm btn-primary" href="{% url 'add_student' %}"><i class="fas fa-plus"></i> Add Student</a> <a class="btn btn-sm btn-primary" href="{% url 'add_student' %}"><i class="fas fa-plus"></i> Add Student</a>
<a class="btn btn-sm btn-primary" href="{% url 'student_list_pdf' %}"><i class="fas fa-download"></i> Download pdf</a> <!--new-->
</div> </div>
{% endif %} {% endif %}

View File

@ -0,0 +1,70 @@
{% block content %}
<style>
.table {
width: 100%;
border-collapse: collapse;
}
.table th, .table td {
padding: 8px;
border: 1px solid #ddd; /* Add thin borders for separation */
text-align: left;
}
.table th {
background-color: #f2f2f2;
}
.title-1 {
font-size: 24px;
margin-bottom: 16px;
}
.text-danger {
color: red;
}
a {
color: black;
text-decoration: none;
}
</style>
<p class="title-1">Lecturers</p>
<div>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>ID No.</th>
<th>Full Name</th>
<th>Email</th>
<th>Mob No.</th>
<th>Address/City</th>
</tr>
</thead>
<tbody>
{% for lecturer in lecturers %}
<tr>
<td> {{ forloop.counter }}.</td>
<td>{{ lecturer.username }}</td>
<td><a href="{% url 'profile_single' lecturer.id %}">{{ lecturer.get_full_name }}</a></td>
<td>{{ lecturer.email }}</td>
<td>{{ lecturer.phone }}</td>
<td>{{ lecturer.address }}</td>
</tr>
{% empty %}
<tr>
<td>
<span class="text-danger">
No Lecturer(s).
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock content %}

View File

@ -0,0 +1,68 @@
{% block content %}
<style>
.table {
width: 100%;
border-collapse: collapse;
}
.table th, .table td {
padding: 8px;
border: 1px solid #ddd; /* Add thin borders for separation */
text-align: left;
}
.table th {
background-color: #f2f2f2;
}
.title-1 {
font-size: 24px;
margin-bottom: 16px;
}
.text-danger {
color: red;
}
a {
color: black;
text-decoration: none;
}
</style>
<p class="title-1">Students</p>
<div>
<table class="table">
<thead>
<tr>
<th>ID No.</th>
<th>Full Name</th>
<th>Email</th>
<th>Mob No.</th>
<th>Program</th>
</tr>
</thead>
<tbody>
{% for student in students %}
<tr>
<td> {{ forloop.counter }}.</td>
<td>{{ student.student.username }}</td>
<td><a href="{% url 'profile_single' student.id %}">{{ student.student.get_full_name }}</a></td>
<td>{{ student.student.email }}</td>
<td>{{ student.program }}</td>
</tr>
{% empty %}
<tr>
<td>
<span class="text-danger">
No Lecturer(s).
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock content %}