implemented basic teaching session pages
This commit is contained in:
parent
cfa65daa19
commit
5f2aaf1a2e
9 changed files with 304 additions and 14 deletions
|
@ -61,9 +61,9 @@ class AdminAttendance(admin.ModelAdmin):
|
|||
|
||||
@admin.register(models.Absence)
|
||||
class AdminAbsence(admin.ModelAdmin):
|
||||
list_display = ("id", "message", "student", "department", "start", "end")
|
||||
search_fields = ("id", "message", "student", "department", "start", "end")
|
||||
list_filter = ("department", "start", "end")
|
||||
list_display = ("id", "message", "student", "start", "end")
|
||||
search_fields = ("id", "message", "student", "start", "end")
|
||||
list_filter = ("start", "end")
|
||||
|
||||
|
||||
@admin.register(models.AbsenceAttachment)
|
||||
|
|
166
Palto/Palto/migrations/0001_initial.py
Normal file
166
Palto/Palto/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,166 @@
|
|||
# Generated by Django 4.2.7 on 2023-12-10 11:31
|
||||
|
||||
import Palto.Palto.models
|
||||
from django.conf import settings
|
||||
import django.contrib.auth.models
|
||||
import django.contrib.auth.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Absence',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('message', models.TextField()),
|
||||
('start', models.DateTimeField()),
|
||||
('end', models.DateTimeField()),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Department',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64, unique=True)),
|
||||
('email', models.EmailField(max_length=254)),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StudentGroup',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_groups', to='Palto.department')),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
|
||||
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
||||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user',
|
||||
'verbose_name_plural': 'users',
|
||||
'abstract': False,
|
||||
},
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TeachingUnit',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teaching_units', to='Palto.department')),
|
||||
('managers', models.ManyToManyField(blank=True, related_name='managing_units', to=settings.AUTH_USER_MODEL)),
|
||||
('student_groups', models.ManyToManyField(blank=True, related_name='studying_units', to='Palto.studentgroup')),
|
||||
('teachers', models.ManyToManyField(blank=True, related_name='teaching_units', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TeachingSession',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('start', models.DateTimeField()),
|
||||
('duration', models.DurationField()),
|
||||
('note', models.TextField(blank=True)),
|
||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teaching_sessions', to='Palto.studentgroup')),
|
||||
('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teaching_sessions', to=settings.AUTH_USER_MODEL)),
|
||||
('unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to='Palto.teachingunit')),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='studentgroup',
|
||||
name='owner',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owning_groups', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='studentgroup',
|
||||
name='students',
|
||||
field=models.ManyToManyField(blank=True, related_name='student_groups', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StudentCard',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('uid', models.BinaryField(max_length=7)),
|
||||
('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_cards', to='Palto.department')),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_cards', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='department',
|
||||
name='managers',
|
||||
field=models.ManyToManyField(blank=True, related_name='managing_departments', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='department',
|
||||
name='students',
|
||||
field=models.ManyToManyField(blank=True, related_name='studying_departments', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='department',
|
||||
name='teachers',
|
||||
field=models.ManyToManyField(blank=True, related_name='teaching_departments', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Attendance',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('date', models.DateTimeField()),
|
||||
('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attendances', to='Palto.teachingsession')),
|
||||
('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attended_sessions', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AbsenceAttachment',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('content', models.FileField(upload_to='absence/attachment/')),
|
||||
('absence', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='Palto.absence')),
|
||||
],
|
||||
bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='absence',
|
||||
name='department',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='absences', to='Palto.department'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='absence',
|
||||
name='student',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='absences', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -63,6 +63,9 @@ class User(AbstractUser, ModelPermissionHelper):
|
|||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} id={str(self.id)[:8]} username={self.username!r}>"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.first_name} {self.last_name.upper()}"
|
||||
|
||||
@staticmethod
|
||||
def multiple_related_departments(users: Iterable["User"]) -> QuerySet["Department"]:
|
||||
"""
|
||||
|
|
5
Palto/Palto/templates/Palto/homepage.html
Normal file
5
Palto/Palto/templates/Palto/homepage.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
{% extends "Palto/base.html" %}
|
||||
|
||||
{% block body %}
|
||||
Hello there.
|
||||
{% endblock %}
|
|
@ -1,3 +1,11 @@
|
|||
{% load static %}
|
||||
|
||||
<nav>
|
||||
Palto
|
||||
<img src="{% static "Palto/favicon.svg" %}" alt="Palto's icon" width="5%">
|
||||
<a>Palto</a>
|
||||
|
||||
<a href="{% url "Palto:homepage" %}">Home</a>
|
||||
<a href="{% url "Palto:my_profile" %}">Profile</a>
|
||||
<a href="{% url "Palto:login" %}">Login</a>
|
||||
<a href="{% url "Palto:logout" %}">Logout</a>
|
||||
</nav>
|
||||
|
|
27
Palto/Palto/templates/Palto/teaching_session.html
Normal file
27
Palto/Palto/templates/Palto/teaching_session.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
{% extends "Palto/base.html" %}
|
||||
|
||||
{% block body %}
|
||||
{# table of all the sessions #}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Identifiant</th>
|
||||
<th>Début</th>
|
||||
<th>Durée</th>
|
||||
<th>Unité d'Enseignement</th>
|
||||
<th>Enseignant</th>
|
||||
<th>Groupe</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ session.id }}</td>
|
||||
<td>{{ session.start }}</td>
|
||||
<td>{{ session.duration }}</td>
|
||||
<td>{{ session.unit }}</td>
|
||||
<td>{{ session.teacher }}</td>
|
||||
<td>{{ session.group }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
36
Palto/Palto/templates/Palto/teaching_session_list.html
Normal file
36
Palto/Palto/templates/Palto/teaching_session_list.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
{% extends "Palto/base.html" %}
|
||||
|
||||
{% block body %}
|
||||
{# table of all the sessions #}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Identifiant</th>
|
||||
<th>Début</th>
|
||||
<th>Durée</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for session in sessions %}
|
||||
<tr>
|
||||
<td><a href="{% url "Palto:teaching_session" session.id %}">{{ session.id }}</a></td>
|
||||
<td>{{ session.start }}</td>
|
||||
<td>{{ session.duration }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{# page navigator #}
|
||||
<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 %}
|
|
@ -16,6 +16,8 @@ urlpatterns = [
|
|||
# User
|
||||
path("login/", views.login_view, name="login"),
|
||||
path("logout/", views.logout_view, name="logout"),
|
||||
path("profile/", views.profile_view, name="profile"),
|
||||
path("profile/", views.profile_view, name="my_profile"),
|
||||
path("profile/<uuid:profile_id>/", views.profile_view, name="profile"),
|
||||
path("teaching_sessions/", views.teaching_session_list_view, name="teaching_session_list"),
|
||||
path("teaching_sessions/<uuid:session_id>/", views.teaching_session_view, name="teaching_session"),
|
||||
]
|
||||
|
|
|
@ -6,20 +6,24 @@ A view is what control the content of a page, prepare the correct data, react to
|
|||
import uuid
|
||||
from django.contrib.auth import login, authenticate, logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.core.paginator import Paginator
|
||||
from django.http import HttpResponseForbidden
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
||||
from Palto.Palto import models
|
||||
from Palto.Palto.forms import LoginForm
|
||||
from Palto.Palto.models import User
|
||||
|
||||
|
||||
ELEMENT_PER_PAGE: int = 30
|
||||
|
||||
|
||||
# Create your views here.
|
||||
def homepage_view(request: HttpRequest):
|
||||
# TODO: homepage
|
||||
return HttpResponse("Hello there.")
|
||||
def homepage_view(request: WSGIRequest):
|
||||
return render(request, "Palto/homepage.html")
|
||||
|
||||
|
||||
def login_view(request: HttpRequest):
|
||||
def login_view(request: WSGIRequest):
|
||||
# create a login form
|
||||
form_login = LoginForm(request.POST)
|
||||
|
||||
|
@ -51,7 +55,7 @@ def login_view(request: HttpRequest):
|
|||
|
||||
|
||||
@login_required
|
||||
def logout_view(request: HttpRequest):
|
||||
def logout_view(request: WSGIRequest):
|
||||
# disconnect the user from the website
|
||||
logout(request)
|
||||
# redirect him to the main page
|
||||
|
@ -59,13 +63,13 @@ def logout_view(request: HttpRequest):
|
|||
|
||||
|
||||
@login_required
|
||||
def profile_view(request: HttpRequest, profile_id: uuid.UUID = None):
|
||||
def profile_view(request: WSGIRequest, profile_id: uuid.UUID = None):
|
||||
if profile_id is None:
|
||||
# if the profile id is not given, redirect to the page of the current user.
|
||||
return redirect("Palto:profile", request.user.id)
|
||||
|
||||
# get the corresponding user from its id.
|
||||
profile = get_object_or_404(User, id=profile_id)
|
||||
profile = get_object_or_404(models.User, id=profile_id)
|
||||
|
||||
# render the page
|
||||
return render(
|
||||
|
@ -75,3 +79,42 @@ def profile_view(request: HttpRequest, profile_id: uuid.UUID = None):
|
|||
profile=profile
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def teaching_session_list_view(request: WSGIRequest):
|
||||
# get all the sessions that the user can see, sorted by starting date
|
||||
raw_sessions = models.TeachingSession.all_visible_by_user(request.user).order_by("start")
|
||||
# paginate them to avoid having too many elements at the same time
|
||||
paginator = Paginator(raw_sessions, ELEMENT_PER_PAGE)
|
||||
|
||||
# get only the session for the requested page
|
||||
page = request.GET.get("page", 0)
|
||||
sessions = paginator.get_page(page)
|
||||
|
||||
# render the page
|
||||
return render(
|
||||
request,
|
||||
"Palto/teaching_session_list.html",
|
||||
context=dict(
|
||||
sessions=sessions
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def teaching_session_view(request: WSGIRequest, session_id: uuid.UUID):
|
||||
session = get_object_or_404(models.TeachingSession, id=session_id)
|
||||
|
||||
if session not in models.TeachingSession.all_visible_by_user(request.user):
|
||||
# TODO: syntaxic sugar session.visible_by_user(request.user)
|
||||
return HttpResponseForbidden()
|
||||
|
||||
# render the page
|
||||
return render(
|
||||
request,
|
||||
"Palto/teaching_session.html",
|
||||
context=dict(
|
||||
session=session
|
||||
)
|
||||
)
|
Loading…
Reference in a new issue