From e21101672cdf269cb1c378f5567a16271767cb91 Mon Sep 17 00:00:00 2001
From: janmax <mail-github@jmx.io>
Date: Mon, 22 May 2017 19:28:17 +0200
Subject: [PATCH] Added overall_score method to student and provided first
 serializers

---
 core/models.py           | 39 ++++++++++++++++++++++++--------
 core/serializers.py      | 49 ++++++++++++++++++++++++++++++++++++++++
 core/views/export_csv.py | 10 +++-----
 3 files changed, 82 insertions(+), 16 deletions(-)
 create mode 100644 core/serializers.py

diff --git a/core/models.py b/core/models.py
index 8be60cc1..c7914751 100644
--- a/core/models.py
+++ b/core/models.py
@@ -43,6 +43,7 @@
 
 from random import sample, randrange
 from string import ascii_lowercase
+from collections import OrderedDict
 
 from django.contrib.auth.models import User
 from django.db import models
@@ -50,6 +51,7 @@ from django.db.models import Q
 
 SLUG_LENGTH = 16
 
+
 def random_slug():
     return ''.join(sample(ascii_lowercase, SLUG_LENGTH))
 
@@ -67,13 +69,13 @@ class SubmissionType(models.Model):
     possible_solution = models.TextField()
     correction_guideline = models.TextField()
 
+    def __str__(self):
+        return self.name
+
     class Meta:
         verbose_name = "SubmissionType"
         verbose_name_plural = "SubmissionType Set"
 
-    def __str__(self):
-        return self.name
-
 
 class Student(models.Model):
     # Fields
@@ -86,17 +88,31 @@ class Student(models.Model):
         limit_choices_to={'groups__name': 'Students'},
     )
 
+    def score_per_submission(self):
+        if self.submissions.all():
+            return OrderedDict({
+                s.type : s.feedback.score if hasattr(s, 'feedback') else 0
+                    for s in self.submissions.all()
+            })
+        else:
+            return OrderedDict({
+                t.name : 0 for t in SubmissionType.objects.all()
+            })
+
+    def overall_score(self):
+        return sum(self.score_per_submission().values())
+
     def disable(self):
         self.has_logged_in = True
         self.save()
 
+    def __str__(self):
+        return self.user.username
+
     class Meta:
         verbose_name = "Student"
         verbose_name_plural = "Student Set"
 
-    def __str__(self):
-        return self.user.username
-
 
 class Submission(models.Model):
 
@@ -111,7 +127,11 @@ class Submission(models.Model):
     )
     text = models.TextField(blank=True)
     pre_corrections = models.TextField(blank=True)
-    student = models.ForeignKey(Student, on_delete=models.CASCADE)
+    student = models.ForeignKey(
+        Student,
+        on_delete=models.CASCADE,
+        related_name='submissions'
+    )
 
     class Meta:
         verbose_name = "Submission"
@@ -145,7 +165,7 @@ class Submission(models.Model):
 
         candidates = cls.objects.filter(
             (
-                  Q(feedback__isnull=True)
+                Q(feedback__isnull=True)
                 | Q(feedback__origin=Feedback.DID_NOT_COMPILE)
                 | Q(feedback__origin=Feedback.COULD_NOT_LINK)
             )
@@ -161,7 +181,8 @@ class Submission(models.Model):
             return False
 
         submission = candidates[0]
-        feedback = submission.feedback if hasattr(submission, 'feedback') else Feedback()
+        feedback = submission.feedback if hasattr(
+            submission, 'feedback') else Feedback()
         feedback.origin = Feedback.MANUAL
         feedback.status = Feedback.EDITABLE
         feedback.of_tutor = tutor
diff --git a/core/serializers.py b/core/serializers.py
new file mode 100644
index 00000000..9323508e
--- /dev/null
+++ b/core/serializers.py
@@ -0,0 +1,49 @@
+
+from rest_framework import serializers
+
+from core.models import SubmissionType, Student
+from django.contrib.auth.models import User
+
+
+class SubmissionTypeSerializer(serializers.ModelSerializer):
+
+    def create(self, validated_data):
+        return SubmissionType(**validated_data)
+
+    class Meta:
+        model = SubmissionType
+        exclude = ('slug', 'correction_guideline',)
+
+
+class CreateStudentSerializer(serializers.ModelSerializer):
+
+    username = serializers.CharField(source='user.username')
+    email    = serializers.CharField(source='user.email')
+    password = serializers.CharField(source='user.password')
+
+    class Meta:
+        model = Student
+        fields = ('username', 'name', 'email', 'matrikel_no', 'password')
+        extra_kwargs = {'password': {'write_only': True}}
+
+    def to_representation(self, obj):
+        return {
+            'username'      : obj.user.username,
+            'name'          : obj.name,
+            'matrikel_no'   : obj.matrikel_no,
+        }
+
+    def create(self, validated_data):
+        user = User(
+            email=validated_data['email'],
+            username=validated_data['username']
+        )
+        user.set_password(validated_data['password'])
+
+        student = Student(
+            name=validated_data['name'],
+            matrikel_no=validated_data['matrikel_no'],
+            user=user,
+        )
+
+        return student
diff --git a/core/views/export_csv.py b/core/views/export_csv.py
index 36065414..93dbffda 100644
--- a/core/views/export_csv.py
+++ b/core/views/export_csv.py
@@ -1,7 +1,7 @@
 import csv
 from django.http import HttpResponse
 
-from core.models import Student, SubmissionType, Submission
+from core.models import Student, SubmissionType
 from core.custom_annotations import group_required
 
 
@@ -16,16 +16,12 @@ def export_csv(request):
                     [s.name for s in SubmissionType.objects.all().order_by('name')])
 
     for student in Student.objects.all():
-        submissions = Submission.objects.filter(student=student)
-        score_list  = [s.feedback.score if hasattr(s, 'feedback') else 0 for s in submissions.order_by('type__name')]
-        if not score_list:
-            score_list = [0] * SubmissionType.objects.count()
         writer.writerow([
             student.matrikel_no,
             student.user.username,
             student.name,
-            sum(score_list),
-            *score_list
+            student.overall_score(),
+            *student.score_per_submission().values()
         ])
 
     return response
-- 
GitLab