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:
commit
8ecbc1c9d7
@ -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
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 %}
|
||||||
|
|
||||||
|
|||||||
@ -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 %}
|
||||||
|
|
||||||
|
|||||||
70
templates/pdf/lecturer_list.html
Normal file
70
templates/pdf/lecturer_list.html
Normal 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 %}
|
||||||
68
templates/pdf/student_list.html
Normal file
68
templates/pdf/student_list.html
Normal 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 %}
|
||||||
Loading…
x
Reference in New Issue
Block a user