diff --git a/api/admin.py b/api/admin.py index cfedc810..d5933479 100644 --- a/api/admin.py +++ b/api/admin.py @@ -3,7 +3,7 @@ from api.models.vak import Vak from api.models.groep import Groep from api.models.project import Project -from api.models.indiening import Indiening +from api.models.indiening import Indiening, IndieningBestand from api.models.score import Score admin.site.register(Gebruiker) @@ -12,3 +12,4 @@ admin.site.register(Project) admin.site.register(Indiening) admin.site.register(Score) +admin.site.register(IndieningBestand) diff --git a/api/models/gebruiker.py b/api/models/gebruiker.py index c2345671..26b8882a 100644 --- a/api/models/gebruiker.py +++ b/api/models/gebruiker.py @@ -4,8 +4,7 @@ class Gebruiker(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True) - subjects = models.ManyToManyField('Vak', related_name='gebruiker_vakken', blank=True) is_lesgever = models.BooleanField(default=False) def __str__(self): - return self.user.first_name + return self.user.first_name + self.user.last_name diff --git a/api/models/groep.py b/api/models/groep.py index 3494ba86..79f44a83 100644 --- a/api/models/groep.py +++ b/api/models/groep.py @@ -2,9 +2,10 @@ class Groep(models.Model): - group_id = models.AutoField(primary_key=True) - students = models.ManyToManyField('Gebruiker', related_name='groep_studenten', blank=True) + groep_id = models.AutoField(primary_key=True) + studenten = models.ManyToManyField('Gebruiker', related_name='groep_studenten', blank=True) project = models.ForeignKey('Project', on_delete=models.CASCADE) def __str__(self): - return f"Group {self.group_id}" + return f"Group {self.groep_id}" + diff --git a/api/models/indiening.py b/api/models/indiening.py index 577062ba..5c1b1097 100644 --- a/api/models/indiening.py +++ b/api/models/indiening.py @@ -1,13 +1,22 @@ from django.db import models + +def upload_to(instance, filename): + return f'data/indieningen/indiening_{instance.indiening_id}/{filename}' class Indiening(models.Model): indiening_id = models.AutoField(primary_key=True) - indiener = models.ForeignKey('Groep', on_delete=models.CASCADE) - indieningsbestanden = models.FileField(upload_to='uploads/') - tijdstip = models.DateTimeField(null=False) - project = models.ForeignKey('Project', on_delete=models.CASCADE, default='0') + groep = models.ForeignKey('Groep', on_delete=models.CASCADE) + tijdstip = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return str(self.indiening_id) + + +class IndieningBestand(models.Model): + indiening_bestand_id = models.AutoField(primary_key=True) + indiening = models.ForeignKey('Indiening', on_delete=models.CASCADE) + bestand = models.FileField(upload_to=upload_to) def __str__(self): - return self.tijdstip - \ No newline at end of file + return str(self.bestand.name) \ No newline at end of file diff --git a/api/models/project.py b/api/models/project.py index 45eb6ee8..58016522 100644 --- a/api/models/project.py +++ b/api/models/project.py @@ -1,14 +1,19 @@ from django.db import models from .vak import Vak +def upload_to(instance, filename): + vak_id = instance.vak.vak_id + return f'data/opgaves/vak_{vak_id}/{filename}' + class Project(models.Model): project_id = models.AutoField(primary_key=True) titel = models.CharField(max_length=100) - description = models.TextField() - opgavebestanden = models.FileField(upload_to='data/opgaves/') + beschrijving = models.TextField() + opgave_bestand = models.FileField(upload_to=upload_to) vak = models.ForeignKey(Vak, on_delete=models.CASCADE) deadline = models.DateTimeField(null=True) + max_score = models.IntegerField(default=20) # indiening restricties def __str__(self): diff --git a/api/models/score.py b/api/models/score.py index 0b6cc20d..ca160dda 100644 --- a/api/models/score.py +++ b/api/models/score.py @@ -2,9 +2,9 @@ class Score(models.Model): + score_id = models.AutoField(primary_key=True) score = models.SmallIntegerField() indiening = models.ForeignKey('Indiening', on_delete=models.CASCADE) - groep = models.ForeignKey('Groep', on_delete=models.CASCADE) def __str__(self): - return self.score + return self.score_id diff --git a/api/models/vak.py b/api/models/vak.py index bdc66f71..77f05be6 100644 --- a/api/models/vak.py +++ b/api/models/vak.py @@ -3,11 +3,11 @@ class Vak(models.Model): vak_id = models.AutoField(primary_key=True) - name = models.CharField(max_length=100) - students = models.ManyToManyField('Gebruiker', related_name='vak_gebruikers', blank=True) - teachers = models.ManyToManyField('Gebruiker', related_name='vak_lesgevers', blank=True) + naam = models.CharField(max_length=100) + studenten = models.ManyToManyField('Gebruiker', related_name='vak_gebruikers', blank=True) + lesgevers = models.ManyToManyField('Gebruiker', related_name='vak_lesgevers', blank=True) def __str__(self): - return self.name + return self.naam diff --git a/api/serializers/gebruiker.py b/api/serializers/gebruiker.py index c2891f36..d03ff176 100644 --- a/api/serializers/gebruiker.py +++ b/api/serializers/gebruiker.py @@ -8,39 +8,10 @@ class Meta: fields = '__all__' def create(self, validated_data): - subjects_data = validated_data.pop('subjects') instance = Gebruiker.objects.create(**validated_data) - instance.subjects.set(subjects_data) - - populate_subject_gebruikers(instance) - return instance def update(self, instance, validated_data): - instance.is_lesgever = validated_data.pop('is_lesgever', False) - - - subjects_data = validated_data.pop('subjects', []) - - depopulate_subject_gebruikers(instance) - - instance.subjects.clear() - instance.subjects.set(subjects_data) - - populate_subject_gebruikers(instance) - + instance.is_lesgever = validated_data.pop('is_lesgever') instance.save() - return instance - - -def populate_subject_gebruikers(gebruiker): - for subject in gebruiker.subjects.all(): - if gebruiker.is_lesgever: - subject.teachers.add(gebruiker) - else: - subject.students.add(gebruiker) - -def depopulate_subject_gebruikers(gebruiker): - for subject in gebruiker.subjects.all(): - subject.students.remove(gebruiker) - subject.teachers.remove(gebruiker) \ No newline at end of file + return instance \ No newline at end of file diff --git a/api/serializers/groep.py b/api/serializers/groep.py index a53984e7..f728467c 100644 --- a/api/serializers/groep.py +++ b/api/serializers/groep.py @@ -8,28 +8,33 @@ class Meta: fields = '__all__' def create(self, validated_data): - students_data = validated_data.pop('students') - - validate_students(students_data) + students_data = validated_data.pop('studenten') + validate_students(students_data, validated_data['project']) instance = Groep.objects.create(**validated_data) - instance.students.set(students_data) + instance.studenten.set(students_data) + return instance - def update(self, validated_data): - students_data = validated_data.pop('students') + def update(self, instance, validated_data): + students_data = validated_data.pop('studenten') + validate_students(students_data, validated_data['project']) - validate_students(students_data) - - instance = Groep.objects.create(**validated_data) - instance.students.set(students_data) - + super().update(instance=instance, validated_data=validated_data) + instance.studenten.set(students_data) instance.save() + return instance -def validate_students(students_data): +def validate_students(students_data, project): + groepen = Groep.objects.filter(project=project) + for student in students_data: if student.is_lesgever: - raise serializers.ValidationError("Alle gebruikers in 'students' moeten studenten zijn!") \ No newline at end of file + raise serializers.ValidationError("Alle gebruikers in 'studenten' moeten studenten zijn!") + + for groep in groepen: + if groep.studenten.contains(student): + raise serializers.ValidationError(f"Gebruiker {student.user.id} zit al in een groep voor dit project") \ No newline at end of file diff --git a/api/serializers/indiening.py b/api/serializers/indiening.py index ce2cf94b..7f4f94be 100644 --- a/api/serializers/indiening.py +++ b/api/serializers/indiening.py @@ -1,18 +1,14 @@ from rest_framework import serializers -from api.models.indiening import Indiening +from api.models.indiening import Indiening, IndieningBestand class IndieningSerializer(serializers.ModelSerializer): class Meta: model = Indiening - fields = '__all__' + fields = ('__all__') - def create(self, validated_data): - # indiener is een groep, dus zeker student(en) - indiening = Indiening.objects.create(**validated_data) - return indiening - - def update(self, instance, validated_data): - instance = Indiening.objects.create(**validated_data) - instance.save() - return instance + +class IndieningBestandSerializer(serializers.ModelSerializer): + class Meta: + model = IndieningBestand + fields = ('__all__') \ No newline at end of file diff --git a/api/serializers/project.py b/api/serializers/project.py index 9b8d1a3a..33484740 100644 --- a/api/serializers/project.py +++ b/api/serializers/project.py @@ -1,7 +1,6 @@ from rest_framework import serializers from api.models.project import Project - -from datetime import datetime +from django.utils import timezone class ProjectSerializer(serializers.ModelSerializer): @@ -11,24 +10,23 @@ class Meta: def create(self, validated_data): deadline = validated_data.pop('deadline') - validate_deadline(deadline) project = Project.objects.create(**validated_data) - project.deadline.set(deadline) + project.deadline = deadline + project.save() return project def update(self, instance, validated_data): deadline = validated_data.pop('deadline') - validate_deadline(deadline) - instance = Project.objects.create(**validated_data) - instance.deadline.set(deadline) + super().update(instance=instance, validated_data=validated_data) + instance.deadline = deadline instance.save() return instance def validate_deadline(deadline): - if deadline <= datetime.now(): + if deadline <= timezone.now(): raise serializers.ValidationError("Deadline moet in de toekomst liggen") \ No newline at end of file diff --git a/api/serializers/score.py b/api/serializers/score.py index 060b98f5..50625d71 100644 --- a/api/serializers/score.py +++ b/api/serializers/score.py @@ -8,11 +8,20 @@ class Meta: fields = '__all__' def create(self, validated_data): - score = Score.objects.create(**validated_data) - return score + if Score.objects.filter(indiening=validated_data.get('indiening')).exists(): + raise serializers.ValidationError("Deze indiening heeft al een bestaande score") + validate_score(validated_data) + return Score.objects.create(**validated_data) def update(self, instance, validated_data): - instance = Score.objects.create(**validated_data) + validate_score(validated_data) + super().update(instance=instance, validated_data=validated_data) instance.save() return instance + +def validate_score(data): + max_score = data.get('indiening').groep.project.max_score + if data['score'] > max_score: + raise serializers.ValidationError(f'Score kan niet hoger zijn dan de maximale score van {max_score}') + diff --git a/api/serializers/vak.py b/api/serializers/vak.py index 5f518e1f..14426212 100644 --- a/api/serializers/vak.py +++ b/api/serializers/vak.py @@ -8,65 +8,35 @@ class Meta: fields = '__all__' def create(self, validated_data): - students_data = validated_data.pop('students') - teachers_data = validated_data.pop('teachers') - projects_data = validated_data.pop('projects') + students_data = validated_data.pop('studenten') + teachers_data = validated_data.pop('lesgevers') validate_students_teachers(students_data, teachers_data) vak = Vak.objects.create(**validated_data) - vak.students.set(students_data) - vak.teachers.set(teachers_data) - vak.projects.set(projects_data) - - populate_student_teacher_vakken(vak) + vak.studenten.set(students_data) + vak.lesgevers.set(teachers_data) return vak def update(self, instance, validated_data): - instance.name = validated_data.pop('name') - - students_data = validated_data.pop('students', []) - teachers_data = validated_data.pop('teachers', []) - projects_data = validated_data.pop('projects', []) + students_data = validated_data.pop('studenten', []) + teachers_data = validated_data.pop('lesgevers', []) validate_students_teachers(students_data, teachers_data) - depopulate_student_teacher_vakken(instance) - - instance.students.clear() - instance.teachers.clear() - instance.projects.clear() - - instance.students.set(students_data) - instance.teachers.set(teachers_data) - instance.projects.set(projects_data) + super().update(instance=instance, validated_data=validated_data) + instance.studenten.set(students_data) + instance.lesgevers.set(teachers_data) instance.save() - - populate_student_teacher_vakken(instance) - return instance def validate_students_teachers(students_data, teachers_data): for student in students_data: if student.is_lesgever: - raise serializers.ValidationError("Alle gebruikers in 'students' moeten studenten zijn") + raise serializers.ValidationError("Alle gebruikers in 'studenten' moeten studenten zijn") for teacher in teachers_data: if not teacher.is_lesgever: - raise serializers.ValidationError("Alle gebruikers in 'teachers' moeten lesgevers zijn") - -def populate_student_teacher_vakken(vak): - for student in vak.students.all(): - student.subjects.add(vak) - - for teacher in vak.teachers.all(): - teacher.subjects.add(vak) - -def depopulate_student_teacher_vakken(vak): - for student in vak.students.all(): - student.subjects.remove(vak) - - for teacher in vak.teachers.all(): - teacher.subjects.remove(vak) \ No newline at end of file + raise serializers.ValidationError("Alle gebruikers in 'lesgevers' moeten lesgevers zijn") \ No newline at end of file diff --git a/api/urls.py b/api/urls.py index 3de95fd8..b25c92db 100644 --- a/api/urls.py +++ b/api/urls.py @@ -22,7 +22,7 @@ from .views.gebruiker import gebruiker_list, gebruiker_detail from .views.vak import vak_list, vak_detail from .views.project import project_list, project_detail -from .views.indiening import indiening_list, indiening_detail +from .views.indiening import indiening_list, indiening_detail, indiening_bestand_list, indiening_bestand_detail from .views.score import score_list, score_detail from .views.groep import groep_list, groep_detail @@ -40,6 +40,8 @@ path('api/projecten//', project_detail), path('api/indieningen/', indiening_list), path('api/indieningen//', indiening_detail), + path('api/indiening_bestanden/', indiening_bestand_list), + path('api/indiening_bestanden//', indiening_bestand_detail), path('api/scores/', score_list), path('api/scores//', score_detail), path('api/groepen/', groep_list), diff --git a/api/utils.py b/api/utils.py index d79a5acd..d1df784c 100644 --- a/api/utils.py +++ b/api/utils.py @@ -7,7 +7,8 @@ 'vakken': '/api/vakken', 'groepen': '/api/groepen', 'indieningen': '/api/indieningen', - 'scores': 'api/scores' + 'scores': 'api/scores', + 'projecten': 'api/projecten' } diff --git a/api/views/gebruiker.py b/api/views/gebruiker.py index b7d5a3e6..2e49f553 100644 --- a/api/views/gebruiker.py +++ b/api/views/gebruiker.py @@ -8,7 +8,7 @@ -@api_view(['GET', 'POST']) +@api_view(['GET']) def gebruiker_list(request): if request.method == 'GET': gebruikers = Gebruiker.objects.all() @@ -16,15 +16,9 @@ def gebruiker_list(request): if 'is_lesgever' in request.GET and request.GET.get('is_lesgever').lower() in ['true', 'false']: gebruikers = gebruikers.filter(is_lesgever = (request.GET.get('is_lesgever').lower() == 'true')) + serializer = GebruikerSerializer(gebruikers, many=True) return Response(serializer.data) - - elif request.method == 'POST': - serializer = GebruikerSerializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['GET', 'PUT']) diff --git a/api/views/groep.py b/api/views/groep.py index e3ba6984..359f9535 100644 --- a/api/views/groep.py +++ b/api/views/groep.py @@ -22,7 +22,7 @@ def groep_list(request, format=None): if "student" in request.GET: try: student = eval(request.GET.get('student')) - groepen = groepen.filter(students=student) + groepen = groepen.filter(studenten=student) except NameError: return Response(status=status.HTTP_400_BAD_REQUEST) diff --git a/api/views/indiening.py b/api/views/indiening.py index 9bf48e74..670c675d 100644 --- a/api/views/indiening.py +++ b/api/views/indiening.py @@ -2,8 +2,8 @@ from rest_framework.response import Response from rest_framework import status -from api.models.indiening import Indiening -from api.serializers.indiening import IndieningSerializer +from api.models.indiening import Indiening, IndieningBestand +from api.serializers.indiening import IndieningSerializer, IndieningBestandSerializer @api_view(['GET', 'POST']) @@ -12,17 +12,10 @@ def indiening_list(request, format=None): if request.method == 'GET': indieningen = Indiening.objects.all() - if "project" in request.GET: - try: - project = eval(request.GET.get('project')) - indieningen = indieningen.filter(project=project) - except NameError: - return Response(status=status.HTTP_400_BAD_REQUEST) - if "groep" in request.GET: try: groep = eval(request.GET.get('groep')) - indieningen = indieningen.filter(indiener=groep) + indieningen = indieningen.filter(groep=groep) except NameError: return Response(status=status.HTTP_400_BAD_REQUEST) @@ -30,13 +23,23 @@ def indiening_list(request, format=None): return Response(serializer.data) elif request.method == 'POST': + if 'indiening_bestanden' not in request.FILES: + return Response({"indiening_bestanden":["This field is required."]}, status=status.HTTP_400_BAD_REQUEST) + serializer = IndieningSerializer(data=request.data) if serializer.is_valid(): serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + indiening = serializer.instance + else: + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + for file in request.FILES.getlist('indiening_bestanden'): + IndieningBestand.objects.create(indiening = indiening, bestand = file) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + -@api_view(['GET', 'PUT', 'DELETE']) +@api_view(['GET', 'DELETE']) def indiening_detail(request, id, format=None): try: indiening = Indiening.objects.get(pk=id) @@ -47,13 +50,36 @@ def indiening_detail(request, id, format=None): serializer = IndieningSerializer(indiening) return Response(serializer.data) - elif request.method == 'PUT': - serializer = IndieningSerializer(indiening, data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - elif request.method == 'DELETE': indiening.delete() return Response(status=status.HTTP_204_NO_CONTENT) + + + +@api_view(['GET']) +def indiening_bestand_list(request, format=None): + + if request.method == 'GET': + indieningen_bestanden = IndieningBestand.objects.all() + + if "indiening" in request.GET: + try: + indiening = eval(request.GET.get('indiening')) + indieningen_bestanden = indieningen_bestanden.filter(indiening=indiening) + except NameError: + return Response(status=status.HTTP_400_BAD_REQUEST) + + serializer = IndieningBestandSerializer(indieningen_bestanden, many=True) + return Response(serializer.data) + + +@api_view(['GET']) +def indiening_bestand_detail(request, id, format=None): + try: + indiening_bestand = IndieningBestand.objects.get(pk=id) + except IndieningBestand.DoesNotExist: + return Response(status=status.HTTP_404_NOT_FOUND) + + if request.method == 'GET': + serializer = IndieningBestandSerializer(indiening_bestand) + return Response(serializer.data) diff --git a/api/views/score.py b/api/views/score.py index 15d4c35f..af5798d5 100644 --- a/api/views/score.py +++ b/api/views/score.py @@ -19,13 +19,6 @@ def score_list(request, format=None): except NameError: return Response(status=status.HTTP_400_BAD_REQUEST) - if "groep" in request.GET: - try: - groep = eval(request.GET.get('groep')) - scores = scores.filter(groep=groep) - except NameError: - return Response(status=status.HTTP_400_BAD_REQUEST) - serializer = ScoreSerializer(scores, many=True) return Response(serializer.data) diff --git a/data/opgaves/opgave_schaakklok.txt b/data/opgaves/opgave_schaakklok.txt deleted file mode 100644 index a613afff..00000000 --- a/data/opgaves/opgave_schaakklok.txt +++ /dev/null @@ -1,3 +0,0 @@ -Dit is de opgave - -joepie diff --git a/data/opgaves/opgave_schaakklok_3R5Z3NY.txt b/data/opgaves/opgave_schaakklok_3R5Z3NY.txt deleted file mode 100644 index a613afff..00000000 --- a/data/opgaves/opgave_schaakklok_3R5Z3NY.txt +++ /dev/null @@ -1,3 +0,0 @@ -Dit is de opgave - -joepie diff --git a/data/opgaves/opgave_schaakklok_bLp0t9b.txt b/data/opgaves/opgave_schaakklok_bLp0t9b.txt deleted file mode 100644 index a613afff..00000000 --- a/data/opgaves/opgave_schaakklok_bLp0t9b.txt +++ /dev/null @@ -1,3 +0,0 @@ -Dit is de opgave - -joepie