refactor: Partie "School"

This commit is contained in:
N3WT DE COMPET
2025-01-12 13:18:34 +01:00
parent 83f4d67a6f
commit 58fe509734
7 changed files with 139 additions and 182 deletions

View File

@ -90,6 +90,9 @@ class ProfileView(APIView):
return JsonResponse(profil_serializer.errors, safe=False)
def delete(self, request, _id):
return bdd.delete_object(Profile, _id)
def infoSession(request):
profilCache = cache.get('session_cache')
if profilCache:

View File

@ -1,5 +1,7 @@
import logging
from django.db.models import Q
from django.http import JsonResponse
from django.core.exceptions import ObjectDoesNotExist
from Subscriptions.models import RegistrationForm, Profile, Student
logger = logging.getLogger('N3wtSchool')
@ -86,3 +88,20 @@ def searchObjects(_objectName, _searchTerm=None, _excludeStates=None):
except _objectName.DoesNotExist:
logging.error(f"Aucun résultat n'a été trouvé - {_objectName.__name__} (recherche: {_searchTerm})")
return None
def delete_object(model_class, object_id, related_field=None):
try:
obj = model_class.objects.get(id=object_id)
if related_field and hasattr(obj, related_field):
related_obj = getattr(obj, related_field)
if related_obj:
related_obj.delete()
obj_name = str(obj) # Utiliser la méthode __str__
obj.delete()
return JsonResponse({'message': f'La suppression de l\'objet {obj_name} a été effectuée avec succès'}, safe=False)
except ObjectDoesNotExist:
return JsonResponse({'error': f'L\'objet {model_class.__name__} n\'existe pas avec cet ID'}, status=404, safe=False)
except Exception as e:
return JsonResponse({'error': f'Une erreur est survenue : {str(e)}'}, status=500, safe=False)

View File

@ -4,7 +4,7 @@ from django.db.models.signals import post_migrate
def create_speciality(sender, **kwargs):
from .models import Speciality
if not Speciality.objects.filter(name='GROUPE').exists():
Speciality.objects.create(name='GROUPE', colorCode='#FF0000')
Speciality.objects.create(name='GROUPE', color_code='#FF0000')
class SchoolConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'

View File

@ -18,22 +18,22 @@ LEVEL_CHOICES = [
class Speciality(models.Model):
name = models.CharField(max_length=100)
updatedDate = models.DateTimeField(auto_now=True)
colorCode = models.CharField(max_length=7, default='#FFFFFF')
updated_date = models.DateTimeField(auto_now=True)
color_code = models.CharField(max_length=7, default='#FFFFFF')
def __str__(self):
return self.name
class Teacher(models.Model):
lastName = models.CharField(max_length=100)
firstName = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
specialities = models.ManyToManyField(Speciality, related_name='teachers')
associatedProfile = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True, blank=True)
updatedDate = models.DateTimeField(auto_now=True)
specialities = models.ManyToManyField(Speciality, blank=True)
associated_profile = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True, blank=True)
updated_date = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.lastName} {self.firstName}"
return f"{self.last_name} {self.first_name}"
class SchoolClass(models.Model):
PLANNING_TYPE_CHOICES = [
@ -42,25 +42,25 @@ class SchoolClass(models.Model):
(3, 'Trimestriel')
]
atmosphereName = models.CharField(max_length=255, null=True, blank=True)
ageGroup = models.JSONField()
numberOfStudents = models.PositiveIntegerField()
teachingLanguage = models.CharField(max_length=255)
schoolYear = models.CharField(max_length=9)
updatedDate = models.DateTimeField(auto_now_add=True)
teachers = models.ManyToManyField(Teacher, related_name='schoolClasses')
atmosphere_name = models.CharField(max_length=255, null=True, blank=True)
age_range = models.JSONField(blank=True)
number_of_students = models.PositiveIntegerField(blank=True)
teaching_language = models.CharField(max_length=255, blank=True)
school_year = models.CharField(max_length=9, blank=True)
updated_date = models.DateTimeField(auto_now_add=True)
teachers = models.ManyToManyField(Teacher, blank=True)
levels = ArrayField(models.IntegerField(choices=LEVEL_CHOICES), default=list)
type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1)
schedule = models.JSONField(default=list)
openingDays = ArrayField(models.IntegerField(), default=list)
time_range = models.JSONField(default=list)
opening_days = ArrayField(models.IntegerField(), default=list)
def __str__(self):
return self.atmosphereName
return self.atmosphere_name
class Planning(models.Model):
level = models.IntegerField(choices=LEVEL_CHOICES, null=True, blank=True)
classModel = models.ForeignKey(SchoolClass, null=True, blank=True, related_name='plannings', on_delete=models.CASCADE)
school_class = models.ForeignKey(SchoolClass, null=True, blank=True, related_name='plannings', on_delete=models.CASCADE)
schedule = JSONField(default=dict)
def __str__(self):
return f'Planning for {self.level} of {self.classModel.atmosphereName}'
return f'Planning for {self.level} of {self.school_class.atmosphere_name}'

View File

@ -9,14 +9,14 @@ from django.utils import timezone
import pytz
class SpecialitySerializer(serializers.ModelSerializer):
creationDateFormatted = serializers.SerializerMethodField()
updated_date_formatted = serializers.SerializerMethodField()
class Meta:
model = Speciality
fields = '__all__'
def get_creationDateFormatted(self, obj):
utc_time = timezone.localtime(obj.updatedDate) # Convert to local time
def get_updated_date_formatted(self, obj):
utc_time = timezone.localtime(obj.updated_date) # Convert to local time
local_tz = pytz.timezone(settings.TZ_APPLI)
local_time = utc_time.astimezone(local_tz)
@ -27,52 +27,44 @@ class TeacherDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = ['id', 'lastName', 'firstName', 'email', 'specialities']
fields = ['id', 'last_name', 'first_name', 'email', 'specialities']
class TeacherSerializer(serializers.ModelSerializer):
specialities = SpecialitySerializer(many=True, read_only=True)
specialties_ids = serializers.PrimaryKeyRelatedField(queryset=Speciality.objects.all(), many=True, source='specialities')
associatedProfile_id = serializers.PrimaryKeyRelatedField(queryset=Profile.objects.all(), source='associatedProfile', write_only=False, read_only=False)
mainClasses = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='schoolClasses')
associatedProfile = ProfileSerializer(read_only=True)
rightLabel = serializers.SerializerMethodField()
rightValue = serializers.SerializerMethodField()
creationDateFormatted = serializers.SerializerMethodField()
specialities = serializers.PrimaryKeyRelatedField(queryset=Speciality.objects.all(), many=True, required=False)
associated_profile = serializers.PrimaryKeyRelatedField(queryset=Profile.objects.all(), required=True)
updated_date_formatted = serializers.SerializerMethodField()
class Meta:
model = Teacher
fields = ['id', 'lastName', 'firstName', 'email', 'specialities', 'specialties_ids', 'mainClasses', 'associatedProfile', 'associatedProfile_id', 'rightLabel', 'rightValue', 'updatedDate', 'creationDateFormatted']
fields = '__all__'
def create(self, validated_data):
specialties_data = validated_data.pop('specialities', None)
associatedProfile = validated_data.pop('associatedProfile', None)
specialities_data = validated_data.pop('specialities', None)
associated_profile = validated_data.pop('associated_profile', None)
teacher = Teacher.objects.create(**validated_data)
teacher.specialities.set(specialties_data)
if associatedProfile:
teacher.associatedProfile = associatedProfile
if specialities_data:
teacher.specialities.set(specialities_data)
if associated_profile:
teacher.associated_profile = associated_profile
teacher.save()
return teacher
def update(self, instance, validated_data):
specialties_data = validated_data.pop('specialities', [])
instance.lastName = validated_data.get('lastName', instance.lastName)
instance.firstName = validated_data.get('firstName', instance.firstName)
specialities_data = validated_data.pop('specialities', [])
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.email = validated_data.get('email', instance.email)
instance.associatedProfile = validated_data.get('associatedProfile', instance.associatedProfile)
instance.associated_profile = validated_data.get('associated_profile', instance.associated_profile)
instance.save()
instance.specialities.set(specialties_data)
if specialities_data:
instance.specialities.set(specialities_data)
return instance
def get_rightLabel(self, obj):
return obj.associatedProfile.get_right_display() if obj.associatedProfile else None
def get_rightValue(self, obj):
return obj.associatedProfile.right if obj.associatedProfile else None
def get_creationDateFormatted(self, obj):
utc_time = timezone.localtime(obj.updatedDate) # Convert to local time
def get_updated_date_formatted(self, obj):
utc_time = timezone.localtime(obj.updated_date) # Convert to local time
local_tz = pytz.timezone(settings.TZ_APPLI)
local_time = utc_time.astimezone(local_tz)
return local_time.strftime("%d-%m-%Y %H:%M")
class PlanningSerializer(serializers.ModelSerializer):
@ -86,65 +78,55 @@ class PlanningSerializer(serializers.ModelSerializer):
return internal_value
class SchoolClassSerializer(serializers.ModelSerializer):
creationDateFormatted = serializers.SerializerMethodField()
teachers = TeacherSerializer(many=True, read_only=True)
teachers_ids = serializers.PrimaryKeyRelatedField(queryset=Teacher.objects.all(), many=True, source='teachers')
students = serializers.SerializerMethodField()
levels = serializers.ListField(child=serializers.ChoiceField(choices=LEVEL_CHOICES))
plannings_read = serializers.SerializerMethodField()
plannings = PlanningSerializer(many=True, write_only=True)
updated_date_formatted = serializers.SerializerMethodField()
teachers = serializers.PrimaryKeyRelatedField(queryset=Teacher.objects.all(), many=True, required=False)
class Meta:
model = SchoolClass
fields = [
'id', 'atmosphereName', 'ageGroup', 'numberOfStudents', 'teachingLanguage',
'teachers', 'teachers_ids', 'schoolYear', 'updatedDate',
'creationDateFormatted', 'students', 'levels', 'type', 'schedule',
'openingDays', 'plannings', 'plannings_read'
]
fields = '__all__'
def create(self, validated_data):
teachers_data = validated_data.pop('teachers', [])
levels_data = validated_data.pop('levels', [])
plannings_data = validated_data.pop('plannings', [])
classModel = SchoolClass.objects.create(
atmosphereName=validated_data.get('atmosphereName', ''),
ageGroup=validated_data.get('ageGroup', []),
numberOfStudents=validated_data.get('numberOfStudents', 0),
teachingLanguage=validated_data.get('teachingLanguage', ''),
schoolYear=validated_data.get('schoolYear', ''),
school_class = SchoolClass.objects.create(
atmosphere_name=validated_data.get('atmosphere_name', ''),
age_range=validated_data.get('age_range', []),
number_of_students=validated_data.get('number_of_students', 0),
teaching_language=validated_data.get('teaching_language', ''),
school_year=validated_data.get('school_year', ''),
levels=levels_data,
type=validated_data.get('type', 1), # Added here
schedule=validated_data.get('schedule', ['08:30', '17:30']), # Added here
openingDays=validated_data.get('openingDays', [1, 2, 4, 5]) # Added here
time_range=validated_data.get('time_range', ['08:30', '17:30']), # Added here
opening_days=validated_data.get('opening_days', [1, 2, 4, 5]) # Added here
)
classModel.teachers.set(teachers_data)
school_class.teachers.set(teachers_data)
for planning_data in plannings_data:
Planning.objects.create(
classModel=classModel,
school_class=school_class,
level=planning_data['level'],
schedule=planning_data.get('schedule', {})
)
return classModel
return school_class
def update(self, instance, validated_data):
teachers_data = validated_data.pop('teachers', [])
levels_data = validated_data.pop('levels', [])
plannings_data = validated_data.pop('plannings', [])
instance.atmosphereName = validated_data.get('atmosphereName', instance.atmosphereName)
instance.ageGroup = validated_data.get('ageGroup', instance.ageGroup)
instance.numberOfStudents = validated_data.get('numberOfStudents', instance.numberOfStudents)
instance.teachingLanguage = validated_data.get('teachingLanguage', instance.teachingLanguage)
instance.schoolYear = validated_data.get('schoolYear', instance.schoolYear)
instance.atmosphere_name = validated_data.get('atmosphere_name', instance.atmosphere_name)
instance.age_range = validated_data.get('age_range', instance.age_range)
instance.number_of_students = validated_data.get('number_of_students', instance.number_of_students)
instance.teaching_language = validated_data.get('teaching_language', instance.teaching_language)
instance.school_year = validated_data.get('school_year', instance.school_year)
instance.levels = levels_data
instance.type = validated_data.get('type', instance.type) # Added here
instance.schedule = validated_data.get('schedule', instance.schedule) # Added here
instance.openingDays = validated_data.get('openingDays', instance.openingDays) # Added here
instance.time_range = validated_data.get('time_range', instance.time_range) # Added here
instance.opening_days = validated_data.get('opening_days', instance.opening_days) # Added here
instance.save()
instance.teachers.set(teachers_data)
@ -161,34 +143,15 @@ class SchoolClassSerializer(serializers.ModelSerializer):
else:
# Create new planning if level not existing
Planning.objects.create(
classModel=instance,
school_class=instance,
level=level,
schedule=planning_data.get('schedule', {})
)
return instance
def get_creationDateFormatted(self, obj):
utc_time = timezone.localtime(obj.updatedDate)
def get_updated_date_formatted(self, obj):
utc_time = timezone.localtime(obj.updated_date)
local_tz = pytz.timezone(settings.TZ_APPLI)
local_time = utc_time.astimezone(local_tz)
return local_time.strftime("%d-%m-%Y %H:%M")
def get_students(self, obj):
studentsList = obj.students.all()
filtered_students = []
for student in studentsList:
registrationForm = bdd.getObject(RegistrationForm, "student__id", student.id)
if registrationForm.status == registrationForm.RegistrationFormStatus.RF_VALIDATED:
filtered_students.append(student)
return StudentSerializer(filtered_students, many=True, read_only=True).data
def get_plannings_read(self, obj):
plannings = obj.plannings.all()
levels_dict = {level: {'level': level, 'planning': None} for level in obj.levels}
for planning in plannings:
if planning.level in levels_dict:
levels_dict[planning.level]['planning'] = PlanningSerializer(planning).data
return list(levels_dict.values())

View File

@ -1,16 +1,16 @@
from django.urls import path, re_path
from School.views import TeachersView, EnseignantView, SpecialitiesView, SpecialityView, ClassesView, ClasseView, PlanningsView, PlanningView
from School.views import TeachersView, TeacherView, SpecialitiesView, SpecialityView, ClassesView, ClasseView, PlanningsView, PlanningView
urlpatterns = [
re_path(r'^teachers$', TeachersView.as_view(), name="teachers"),
re_path(r'^teacher$', EnseignantView.as_view(), name="teacher"),
re_path(r'^teacher/([0-9]+)$', EnseignantView.as_view(), name="teacher"),
re_path(r'^specialities$', SpecialitiesView.as_view(), name="specialities"),
re_path(r'^speciality$', SpecialityView.as_view(), name="speciality"),
re_path(r'^speciality/([0-9]+)$', SpecialityView.as_view(), name="speciality"),
re_path(r'^teachers$', TeachersView.as_view(), name="teachers"),
re_path(r'^teacher$', TeacherView.as_view(), name="teacher"),
re_path(r'^teacher/([0-9]+)$', TeacherView.as_view(), name="teacher"),
re_path(r'^schoolClasses$', ClassesView.as_view(), name="schoolClasses"),
re_path(r'^schoolClass$', ClasseView.as_view(), name="schoolClass"),
re_path(r'^schoolClass/([0-9]+)$', ClasseView.as_view(), name="schoolClass"),

View File

@ -4,59 +4,11 @@ from django.utils.decorators import method_decorator
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from .models import Teacher, Speciality, SchoolClass, Planning
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer
from N3wtSchool import bdd
class TeachersView(APIView):
def get(self, request):
teachersList=bdd.getAllObjects(Teacher)
teachers_serializer=TeacherSerializer(teachersList, many=True)
return JsonResponse(teachers_serializer.data, safe=False)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class EnseignantView(APIView):
def get (self, request, _id):
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
teacher_serializer=TeacherSerializer(teacher)
return JsonResponse(teacher_serializer.data, safe=False)
def post(self, request):
teacher_data=JSONParser().parse(request)
teacher_serializer = TeacherSerializer(data=teacher_data)
if teacher_serializer.is_valid():
teacher_serializer.save()
return JsonResponse(teacher_serializer.data, safe=False)
return JsonResponse(teacher_serializer.errors, safe=False)
def put(self, request, _id):
teacher_data=JSONParser().parse(request)
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
teacher_serializer = TeacherSerializer(teacher, data=teacher_data)
if teacher_serializer.is_valid():
teacher_serializer.save()
return JsonResponse(teacher_serializer.data, safe=False)
return JsonResponse(teacher_serializer.errors, safe=False)
def delete(self, request, _id):
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
if teacher is not None:
if teacher.profilAssocie:
print('Suppression du profil associé')
teacher.profilAssocie.delete()
teacher.delete()
return JsonResponse({'message': 'La suppression de l\'teacher a été effectuée avec succès'}, safe=False)
else:
return JsonResponse({'erreur': 'L\'teacher n\'a pas été trouvé'}, safe=False)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class SpecialitiesView(APIView):
@ -116,11 +68,47 @@ class SpecialityView(APIView):
return JsonResponse(speciality_serializer.errors, safe=False)
def delete(self, request, _id):
speciality = bdd.getObject(_objectName=Speciality, _columnName='id', _value=_id)
if speciality != None:
speciality.delete()
return bdd.delete_object(Speciality, _id)
return JsonResponse("La suppression de la spécialité a été effectuée avec succès", safe=False)
class TeachersView(APIView):
def get(self, request):
teachersList=bdd.getAllObjects(Teacher)
teachers_serializer=TeacherSerializer(teachersList, many=True)
return JsonResponse(teachers_serializer.data, safe=False)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class TeacherView(APIView):
def get (self, request, _id):
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
teacher_serializer=TeacherSerializer(teacher)
return JsonResponse(teacher_serializer.data, safe=False)
def post(self, request):
teacher_data=JSONParser().parse(request)
teacher_serializer = TeacherSerializer(data=teacher_data)
if teacher_serializer.is_valid():
teacher_serializer.save()
return JsonResponse(teacher_serializer.data, safe=False)
return JsonResponse(teacher_serializer.errors, safe=False)
def put(self, request, _id):
teacher_data=JSONParser().parse(request)
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
teacher_serializer = TeacherSerializer(teacher, data=teacher_data)
if teacher_serializer.is_valid():
teacher_serializer.save()
return JsonResponse(teacher_serializer.data, safe=False)
return JsonResponse(teacher_serializer.errors, safe=False)
def delete(self, request, _id):
return bdd.delete_object(Teacher, _id, related_field='associated_profile')
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
@ -180,23 +168,7 @@ class ClasseView(APIView):
return JsonResponse(classe_serializer.errors, safe=False)
def delete(self, request, _id):
schoolClass = bdd.getObject(_objectName=SchoolClass, _columnName='id', _value=_id)
if schoolClass is not None:
# Supprimer les plannings associés à la schoolClass
for planning in schoolClass.plannings.all():
print(f'Planning à supprimer : {planning}')
planning.delete()
# Retirer la schoolClass des élèves associés
for eleve in schoolClass.eleves.all():
print(f'Student à retirer de la schoolClass : {eleve}')
eleve.classeAssociee = None
eleve.save()
# Supprimer la schoolClass
schoolClass.delete()
return JsonResponse("La suppression de la schoolClass a été effectuée avec succès", safe=False)
return bdd.delete_object(SchoolClass, _id)
@method_decorator(csrf_protect, name='dispatch')