added additional pages (department, absence list, student groups)
This commit is contained in:
parent
c3c4623931
commit
2f2332766e
13 changed files with 255 additions and 32 deletions
|
@ -24,38 +24,45 @@ class AdminUser(admin.ModelAdmin):
|
||||||
class AdminDepartment(admin.ModelAdmin):
|
class AdminDepartment(admin.ModelAdmin):
|
||||||
list_display = ("id", "name", "email")
|
list_display = ("id", "name", "email")
|
||||||
search_fields = ("id", "name", "email")
|
search_fields = ("id", "name", "email")
|
||||||
|
readonly_fields = ("id",)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.StudentGroup)
|
@admin.register(models.StudentGroup)
|
||||||
class AdminStudentGroup(admin.ModelAdmin):
|
class AdminStudentGroup(admin.ModelAdmin):
|
||||||
list_display = ("id", "name", "owner", "department")
|
list_display = ("id", "name", "owner", "department")
|
||||||
search_fields = ("id", "name", "owner", "department")
|
search_fields = ("id", "name", "owner", "department")
|
||||||
|
list_filter = ("department",)
|
||||||
|
readonly_fields = ("id",)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.TeachingUnit)
|
@admin.register(models.TeachingUnit)
|
||||||
class AdminTeachingUnit(admin.ModelAdmin):
|
class AdminTeachingUnit(admin.ModelAdmin):
|
||||||
list_display = ("id", "name", "email")
|
list_display = ("id", "name", "email")
|
||||||
search_fields = ("id", "name", "email")
|
search_fields = ("id", "name", "email")
|
||||||
|
readonly_fields = ("id",)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.StudentCard)
|
@admin.register(models.StudentCard)
|
||||||
class AdminStudentCard(admin.ModelAdmin):
|
class AdminStudentCard(admin.ModelAdmin):
|
||||||
list_display = ("id", "uid", "owner")
|
list_display = ("id", "uid", "department", "owner")
|
||||||
search_fields = ("id", "uid", "owner")
|
search_fields = ("id", "uid", "department", "owner")
|
||||||
readonly_fields = ("uid",)
|
readonly_fields = ("id", "uid",)
|
||||||
|
list_filter = ("department",)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.TeachingSession)
|
@admin.register(models.TeachingSession)
|
||||||
class AdminTeachingSession(admin.ModelAdmin):
|
class AdminTeachingSession(admin.ModelAdmin):
|
||||||
list_display = ("id", "start", "end", "duration", "teacher")
|
list_display = ("id", "start", "end", "unit", "duration", "teacher")
|
||||||
search_fields = ("id", "start", "end", "duration", "teacher")
|
search_fields = ("id", "start", "end", "unit", "duration", "teacher")
|
||||||
list_filter = ("start", "duration")
|
readonly_fields = ("id",)
|
||||||
|
list_filter = ("unit",)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.Attendance)
|
@admin.register(models.Attendance)
|
||||||
class AdminAttendance(admin.ModelAdmin):
|
class AdminAttendance(admin.ModelAdmin):
|
||||||
list_display = ("id", "date", "student")
|
list_display = ("id", "date", "student")
|
||||||
search_fields = ("id", "date", "student")
|
search_fields = ("id", "date", "student")
|
||||||
|
readonly_fields = ("id",)
|
||||||
list_filter = ("date",)
|
list_filter = ("date",)
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,6 +70,7 @@ class AdminAttendance(admin.ModelAdmin):
|
||||||
class AdminAbsence(admin.ModelAdmin):
|
class AdminAbsence(admin.ModelAdmin):
|
||||||
list_display = ("id", "message", "student", "start", "end")
|
list_display = ("id", "message", "student", "start", "end")
|
||||||
search_fields = ("id", "message", "student", "start", "end")
|
search_fields = ("id", "message", "student", "start", "end")
|
||||||
|
readonly_fields = ("id",)
|
||||||
list_filter = ("start", "end")
|
list_filter = ("start", "end")
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,3 +78,4 @@ class AdminAbsence(admin.ModelAdmin):
|
||||||
class AdminAbsenceAttachment(admin.ModelAdmin):
|
class AdminAbsenceAttachment(admin.ModelAdmin):
|
||||||
list_display = ("id", "content", "absence")
|
list_display = ("id", "content", "absence")
|
||||||
search_fields = ("id", "content", "absence")
|
search_fields = ("id", "content", "absence")
|
||||||
|
readonly_fields = ("id",)
|
||||||
|
|
|
@ -39,17 +39,31 @@ class ModelPermissionHelper:
|
||||||
@classmethod
|
@classmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||||
|
"""
|
||||||
|
Return the list of object that the user can edit
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_editable_by_user(self, user: "User") -> bool:
|
||||||
"""
|
"""
|
||||||
Return True if the user can edit this object
|
Return True if the user can edit this object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
return self in self.all_editable_by_user(user)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def all_visible_by_user(cls, user: "User") -> QuerySet:
|
def all_visible_by_user(cls, user: "User") -> QuerySet:
|
||||||
|
"""
|
||||||
|
Return the list of object that the user can see
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_visible_by_user(self, user: "User") -> bool:
|
||||||
"""
|
"""
|
||||||
Return True if the user can see this object
|
Return True if the user can see this object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
return self in self.all_visible_by_user(user)
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser, ModelPermissionHelper):
|
class User(AbstractUser, ModelPermissionHelper):
|
||||||
"""
|
"""
|
||||||
|
@ -522,6 +536,17 @@ class TeachingSession(models.Model, ModelPermissionHelper):
|
||||||
def end(self) -> datetime:
|
def end(self) -> datetime:
|
||||||
return self.start + self.duration
|
return self.start + self.duration
|
||||||
|
|
||||||
|
@property
|
||||||
|
def related_absences(self) -> QuerySet["Absence"]:
|
||||||
|
"""
|
||||||
|
Return the sessions that match the user absence
|
||||||
|
"""
|
||||||
|
|
||||||
|
return Absence.objects.filter(
|
||||||
|
student__in=self.group.students,
|
||||||
|
start__lte=self.start, end__gte=self.end
|
||||||
|
).distinct()
|
||||||
|
|
||||||
# validations
|
# validations
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
42
Palto/Palto/templates/Palto/absence_list.html
Normal file
42
Palto/Palto/templates/Palto/absence_list.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
{% extends "Palto/base.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{# table of all the absences #}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Identifiant</th>
|
||||||
|
<th>Département</th>
|
||||||
|
<th>Étudiant</th>
|
||||||
|
<th>Période</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{# show the information for every session #}
|
||||||
|
{% for absence in absences %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "Palto:absence_view" absence.id %}">{{ absence.short_id }}</a></td>
|
||||||
|
<td><a href="{% url "Palto:department_view" absence.department.id %}">{{ absence.department }}</a></td>
|
||||||
|
<td><a href="{% url "Palto:profile" absence.student.id %}">{{ absence.student }}</a></td>
|
||||||
|
<td>{{ absence.start }}<br>{{ absence.end }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{# page navigator #}
|
||||||
|
{# TODO(Faraphel): page navigator as template ? #}
|
||||||
|
{# TODO(Faraphel): new absence button #}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% if sessions.has_previous %}
|
||||||
|
<a href="?page={{ sessions.previous_page_number }}">Previous</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<a>{{ sessions.number }}</a>
|
||||||
|
|
||||||
|
{% if sessions.has_next %}
|
||||||
|
<a href="?page={{ sessions.next_page_number }}">Next</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -9,7 +9,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Département</th>
|
<th>Département</th>
|
||||||
<td><a href="{# TODO(Faraphel): departement #}">{{ absence.department }}</a></td>
|
<td><a href="{% url "Palto:department_view" absence.department.id %}">{{ absence.department }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Étudiant</th>
|
<th>Étudiant</th>
|
||||||
|
|
53
Palto/Palto/templates/Palto/department_view.html
Normal file
53
Palto/Palto/templates/Palto/department_view.html
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{% extends "Palto/base.html" %}
|
||||||
|
{% load dict_tags %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{# department's information #}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Identifiant</th>
|
||||||
|
<td>{{ department.id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<td>{{ department.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Mail</th>
|
||||||
|
<td>{% if department.email != None %}{{ department.email }}{% else %} / {% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{# department's managers #}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Responsables</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for manager in department.managers.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "Palto:profile" manager.id %}">{{ manager }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{# department's teachers #}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Enseignants</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for teacher in department.teachers.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "Palto:profile" teacher.id %}">{{ teacher }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
|
@ -1,5 +1,9 @@
|
||||||
{% extends "Palto/base.html" %}
|
{% extends "Palto/base.html" %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
Hello there.
|
<h1>Palto</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Palto est un outil de gestion des présences d'élèves dans vos établissements scolaires.
|
||||||
|
</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
{% for department, profile_department_data in profile_departments_data.items %}
|
{% for department, profile_department_data in profile_departments_data.items %}
|
||||||
<tr>
|
<tr>
|
||||||
{# department name #}
|
{# department name #}
|
||||||
<th>{{ department.name }}</th>
|
<th><a href="{% url "Palto:department_view" department.id %}">{{ department.name }}</a></th>
|
||||||
{# relation information #}
|
{# relation information #}
|
||||||
<td>
|
<td>
|
||||||
<table>
|
<table>
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
<td>Groupe Étudiant</td>
|
<td>Groupe Étudiant</td>
|
||||||
<td>
|
<td>
|
||||||
{% for student_group in student_groups %}
|
{% for student_group in student_groups %}
|
||||||
<a href="{# TODO(Faraphel): redirect to group #}">{{ student_group.name }}</a>
|
<a href="{% url "Palto:student_group_view" student_group.id %}">{{ student_group.name }}</a>
|
||||||
{% if not forloop.last %}<br/>{% endif %}
|
{% if not forloop.last %}<br/>{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
|
|
39
Palto/Palto/templates/Palto/student_group.html
Normal file
39
Palto/Palto/templates/Palto/student_group.html
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{% extends "Palto/base.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{# group's information #}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Identifiant</th>
|
||||||
|
<td>{{ group.id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<td>{{ group.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Département</th>
|
||||||
|
<td><a href="{% url "Palto:department_view" group.department.id %}">{{ group.department }}</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Propriétaire</th>
|
||||||
|
<td><a href="{% url "Palto:profile" group.owner.id %}">{{ group.owner }}</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{# group's students information #}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Étudiants</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for student in group.students.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "Palto:profile" student.id %}">{{ student }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
|
@ -26,7 +26,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Groupe</th>
|
<th>Groupe</th>
|
||||||
<td>{{ session.group }}</td>
|
<td><a href="{% url "Palto:student_group_view" session.group.id %}">{{ session.group }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Département</th>
|
<th>Département</th>
|
||||||
<td href="{# TODO(Faraphel): department url #}">{{ unit.department.name }}</td>
|
<td href="{% url "Palto:department_view" unit.department.id %}">{{ unit.department.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Mail</th>
|
<th>Mail</th>
|
||||||
|
|
|
@ -19,6 +19,12 @@ urlpatterns = [
|
||||||
path("profile/", views.profile_view, name="my_profile"),
|
path("profile/", views.profile_view, name="my_profile"),
|
||||||
path("profile/<uuid:profile_id>/", views.profile_view, name="profile"),
|
path("profile/<uuid:profile_id>/", views.profile_view, name="profile"),
|
||||||
|
|
||||||
|
# Student groups
|
||||||
|
path("student_groups/view/<uuid:group_id>/", views.student_group_view, name="student_group_view"),
|
||||||
|
|
||||||
|
# Departments
|
||||||
|
path("departments/view/<uuid:department_id>/", views.department_view, name="department_view"),
|
||||||
|
|
||||||
# Units
|
# Units
|
||||||
path("teaching_units/view/<uuid:unit_id>/", views.teaching_unit_view, name="teaching_unit_view"),
|
path("teaching_units/view/<uuid:unit_id>/", views.teaching_unit_view, name="teaching_unit_view"),
|
||||||
|
|
||||||
|
@ -27,6 +33,7 @@ urlpatterns = [
|
||||||
path("teaching_sessions/view/<uuid:session_id>/", views.teaching_session_view, name="teaching_session_view"),
|
path("teaching_sessions/view/<uuid:session_id>/", views.teaching_session_view, name="teaching_session_view"),
|
||||||
|
|
||||||
# Absences
|
# Absences
|
||||||
|
path("absences/", views.absence_list_view, name="absence_list"),
|
||||||
path("absences/view/<uuid:absence_id>/", views.absence_view, name="absence_view"),
|
path("absences/view/<uuid:absence_id>/", views.absence_view, name="absence_view"),
|
||||||
path("absences/new/", views.new_absence_view, name="absence_new"),
|
path("absences/new/", views.new_absence_view, name="absence_new"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db.models import Model, Manager
|
from django.db.models import Model, QuerySet
|
||||||
|
|
||||||
|
|
||||||
def get_object_or_none(manager: Manager, *args, **kwargs) -> Optional[Model]:
|
def get_object_or_none(manager: QuerySet, *args, **kwargs) -> Optional[Model]:
|
||||||
"""
|
"""
|
||||||
Similar to the Manager.get method, but return None instead of raising an error.
|
Similar to the Manager.get method, but return None instead of raising an error.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,7 +8,6 @@ from django.contrib.auth import login, authenticate, logout
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.db import IntegrityError
|
|
||||||
from django.http import HttpResponseForbidden
|
from django.http import HttpResponseForbidden
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ def profile_view(request: WSGIRequest, profile_id: uuid.UUID = None):
|
||||||
profile = get_object_or_404(models.User, id=profile_id)
|
profile = get_object_or_404(models.User, id=profile_id)
|
||||||
|
|
||||||
# check if the user is allowed to see this specific object
|
# check if the user is allowed to see this specific object
|
||||||
if profile not in models.User.all_visible_by_user(request.user):
|
if not profile.is_visible_by_user(request.user):
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
# prepare the data and the "complex" query for the template
|
# prepare the data and the "complex" query for the template
|
||||||
|
@ -124,8 +123,7 @@ def teaching_unit_view(request: WSGIRequest, unit_id: uuid.UUID):
|
||||||
unit = get_object_or_404(models.TeachingUnit, id=unit_id)
|
unit = get_object_or_404(models.TeachingUnit, id=unit_id)
|
||||||
|
|
||||||
# check if the user is allowed to see this specific object
|
# check if the user is allowed to see this specific object
|
||||||
if unit not in models.TeachingUnit.all_visible_by_user(request.user):
|
if not unit.is_visible_by_user(request.user):
|
||||||
# TODO(Faraphel): syntaxic sugar session.visible_by_user(request.user)
|
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
# render the page
|
# render the page
|
||||||
|
@ -143,23 +141,14 @@ def teaching_session_view(request: WSGIRequest, session_id: uuid.UUID):
|
||||||
session = get_object_or_404(models.TeachingSession, id=session_id)
|
session = get_object_or_404(models.TeachingSession, id=session_id)
|
||||||
|
|
||||||
# check if the user is allowed to see this specific object
|
# check if the user is allowed to see this specific object
|
||||||
if session not in models.TeachingSession.all_visible_by_user(request.user):
|
if not session.is_visible_by_user(request.user):
|
||||||
# TODO(Faraphel): syntaxic sugar session.visible_by_user(request.user)
|
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
# prepare the data and the "complex" query for the template
|
# prepare the data and the "complex" query for the template
|
||||||
session_students_data = {
|
session_students_data = {
|
||||||
student: {
|
student: {
|
||||||
"attendance": get_object_or_none(
|
"attendance": get_object_or_none(models.Attendance.objects, session=session, student=student),
|
||||||
models.Attendance.objects,
|
"absence": get_object_or_none(session.related_absences, student=student)
|
||||||
session=session,
|
|
||||||
student=student
|
|
||||||
),
|
|
||||||
"absence": get_object_or_none(
|
|
||||||
models.Absence.objects,
|
|
||||||
student=student,
|
|
||||||
start__lte=session.start, end__gte=session.end
|
|
||||||
), # TODO(Faraphel): property ?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for student in session.group.students.all()
|
for student in session.group.students.all()
|
||||||
|
@ -181,8 +170,7 @@ def absence_view(request: WSGIRequest, absence_id: uuid.UUID):
|
||||||
absence = get_object_or_404(models.Absence, id=absence_id)
|
absence = get_object_or_404(models.Absence, id=absence_id)
|
||||||
|
|
||||||
# check if the user is allowed to see this specific object
|
# check if the user is allowed to see this specific object
|
||||||
if absence not in models.Absence.all_visible_by_user(request.user):
|
if not absence.is_visible_by_user(request.user):
|
||||||
# TODO(Faraphel): syntaxic sugar session.visible_by_user(request.user)
|
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
# render the page
|
# render the page
|
||||||
|
@ -236,3 +224,59 @@ def new_absence_view(request: WSGIRequest):
|
||||||
form_new_absence=form_new_absence,
|
form_new_absence=form_new_absence,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def absence_list_view(request):
|
||||||
|
# get all the absences that the user can see, sorted by starting date
|
||||||
|
raw_absences = models.Absence.all_visible_by_user(request.user).order_by("start")
|
||||||
|
# paginate them to avoid having too many elements at the same time
|
||||||
|
paginator = Paginator(raw_absences, ELEMENT_PER_PAGE)
|
||||||
|
|
||||||
|
# get only the session for the requested page
|
||||||
|
page = request.GET.get("page", 0)
|
||||||
|
absences = paginator.get_page(page)
|
||||||
|
|
||||||
|
# render the page
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"Palto/absence_list.html",
|
||||||
|
context=dict(
|
||||||
|
absences=absences
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def department_view(request: WSGIRequest, department_id: uuid.UUID):
|
||||||
|
department = get_object_or_404(models.Department, id=department_id)
|
||||||
|
|
||||||
|
# check if the user is allowed to see this specific object
|
||||||
|
if not department.is_visible_by_user(request.user):
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
# render the page
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"Palto/department_view.html",
|
||||||
|
context=dict(
|
||||||
|
department=department,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def student_group_view(request: WSGIRequest, group_id: uuid.UUID):
|
||||||
|
group = get_object_or_404(models.StudentGroup, id=group_id)
|
||||||
|
|
||||||
|
# check if the user is allowed to see this specific object
|
||||||
|
if not group.is_visible_by_user(request.user):
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
# render the page
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"Palto/student_group.html",
|
||||||
|
context=dict(
|
||||||
|
group=group,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue