Skip to content
Snippets Groups Projects
Verified Commit cc88f2c7 authored by Jan Maximilian Michal's avatar Jan Maximilian Michal
Browse files

Modifications that syncronize several previously merged branches

* Fixed errors that arose from merging errors
* Added feedback to mock data so student page works
* Student serializer now only send necessary submission info on initial load
parent 41852415
No related branches found
No related tags found
1 merge request!39Modifications that syncronize several previously merged branches
Pipeline #
...@@ -7,8 +7,8 @@ from rest_framework.validators import UniqueValidator ...@@ -7,8 +7,8 @@ from rest_framework.validators import UniqueValidator
from core import models from core import models
from core.models import (ExamType, Feedback, GeneralTaskSubscription, from core.models import (ExamType, Feedback, GeneralTaskSubscription,
StudentInfo, Submission, SubmissionType, StudentInfo, Submission, SubmissionType, Test,
TutorSubmissionAssignment) TutorSubmissionAssignment, UserAccount)
from util.factories import GradyUserFactory from util.factories import GradyUserFactory
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -25,7 +25,20 @@ class CannotSetFirstFeedbackFinal(Exception): ...@@ -25,7 +25,20 @@ class CannotSetFirstFeedbackFinal(Exception):
class DynamicFieldsModelSerializer(DynamicFieldsMixin, class DynamicFieldsModelSerializer(DynamicFieldsMixin,
serializers.ModelSerializer): serializers.ModelSerializer):
pass
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
class ExamSerializer(DynamicFieldsModelSerializer): class ExamSerializer(DynamicFieldsModelSerializer):
...@@ -138,47 +151,67 @@ class FeedbackCommentSerializer(serializers.ModelSerializer): ...@@ -138,47 +151,67 @@ class FeedbackCommentSerializer(serializers.ModelSerializer):
read_only_fields = ('created',) read_only_fields = ('created',)
class SubmissionTypeSerializer(DynamicFieldsModelSerializer): class TestSerializer(DynamicFieldsModelSerializer):
fullScore = serializers.ReadOnlyField(source='full_score')
typeId = serializers.ReadOnlyField(source='id') class Meta:
model = Test
fields = ('name', 'label', 'annotation')
class SubmissionTypeListSerializer(DynamicFieldsModelSerializer):
fullScore = serializers.IntegerField(source='full_score')
class Meta:
model = SubmissionType
fields = ('id', 'name', 'fullScore')
class SubmissionTypeSerializer(SubmissionTypeListSerializer):
class Meta: class Meta:
model = SubmissionType model = SubmissionType
fields = ('typeId', 'name', 'fullScore', 'description', 'solution') fields = ('id', 'name', 'fullScore', 'description', 'solution')
class SubmissionSerializer(DynamicFieldsModelSerializer): class SubmissionSerializer(DynamicFieldsModelSerializer):
feedback = serializers.ReadOnlyField(source='feedback.text') type = SubmissionTypeSerializer()
score = serializers.ReadOnlyField(source='feedback.score') feedback = FeedbackSerializer()
typeId = serializers.ReadOnlyField(source='type.id') tests = TestSerializer(many=True)
typeName = serializers.ReadOnlyField(source='type.name')
fullScore = serializers.ReadOnlyField(source='type.full_score') class Meta:
model = Submission
fields = ('type', 'text', 'feedback', 'tests')
class SubmissionListSerializer(DynamicFieldsModelSerializer):
type = SubmissionTypeListSerializer(fields=('id', 'name', 'fullScore'))
# TODO change this according to new feedback model
feedback = FeedbackSerializer(fields=('score',))
class Meta: class Meta:
model = Submission model = Submission
fields = ('typeId', 'typeName', 'text', fields = ('type', 'feedback')
'feedback', 'score', 'fullScore')
class StudentInfoSerializer(DynamicFieldsModelSerializer): class StudentInfoSerializer(DynamicFieldsModelSerializer):
name = serializers.ReadOnlyField(source='user.fullname') name = serializers.ReadOnlyField(source='user.fullname')
user = serializers.ReadOnlyField(source='user.username') matrikel_no = serializers.ReadOnlyField(source='user.matrikel_no')
exam = ExamSerializer() exam = ExamSerializer()
submissions = SubmissionSerializer(many=True) submissions = SubmissionListSerializer(many=True)
class Meta: class Meta:
model = StudentInfo model = StudentInfo
fields = ('name', 'user', 'exam', 'submissions') fields = ('name', 'user', 'matrikel_no', 'exam', 'submissions')
class SubmissionNoTextFieldsSerializer(DynamicFieldsModelSerializer): class SubmissionNoTextFieldsSerializer(DynamicFieldsModelSerializer):
score = serializers.ReadOnlyField(source='feedback.score') score = serializers.ReadOnlyField(source='feedback.score')
typeId = serializers.ReadOnlyField(source='type.id') type = serializers.ReadOnlyField(source='type.name')
fullScore = serializers.ReadOnlyField(source='type.full_score') fullScore = serializers.ReadOnlyField(source='type.full_score')
class Meta: class Meta:
model = Submission model = Submission
fields = ('typeId', 'score', 'fullScore') fields = ('type', 'score', 'fullScore')
class StudentInfoSerializerForListView(DynamicFieldsModelSerializer): class StudentInfoSerializerForListView(DynamicFieldsModelSerializer):
...@@ -196,13 +229,13 @@ class TutorSerializer(DynamicFieldsModelSerializer): ...@@ -196,13 +229,13 @@ class TutorSerializer(DynamicFieldsModelSerializer):
feedback_count = serializers.IntegerField(source='get_feedback_count', feedback_count = serializers.IntegerField(source='get_feedback_count',
read_only=True) read_only=True)
def create(self, validated_data) -> models.UserAccount: def create(self, validated_data) -> UserAccount:
log.info("Crating tutor from data %s", validated_data) log.info("Crating tutor from data %s", validated_data)
return user_factory.make_tutor( return user_factory.make_tutor(
username=validated_data['username']) username=validated_data['username'])
class Meta: class Meta:
model = models.UserAccount model = UserAccount
fields = ('username', 'feedback_count') fields = ('username', 'feedback_count')
......
...@@ -49,7 +49,8 @@ class StudentPageTests(APITestCase): ...@@ -49,7 +49,8 @@ class StudentPageTests(APITestCase):
}] }]
}) })
self.student = self.test_data['students'][0].student self.student = self.test_data['students'][0]
self.student_info = self.student.student
self.tutor = self.test_data['tutors'][0] self.tutor = self.test_data['tutors'][0]
self.reviewer = self.test_data['reviewers'][0] self.reviewer = self.test_data['reviewers'][0]
self.submission = self.test_data['submissions'][0] self.submission = self.test_data['submissions'][0]
...@@ -57,7 +58,7 @@ class StudentPageTests(APITestCase): ...@@ -57,7 +58,7 @@ class StudentPageTests(APITestCase):
self.request = self.factory.get(reverse('student-page')) self.request = self.factory.get(reverse('student-page'))
self.view = StudentSelfApiView.as_view() self.view = StudentSelfApiView.as_view()
force_authenticate(self.request, user=self.student.user) force_authenticate(self.request, user=self.student)
self.response = self.view(self.request) self.response = self.view(self.request)
self.exam_obj = self.response.data['exam'] self.exam_obj = self.response.data['exam']
...@@ -66,7 +67,7 @@ class StudentPageTests(APITestCase): ...@@ -66,7 +67,7 @@ class StudentPageTests(APITestCase):
def test_student_information_contains_name(self): def test_student_information_contains_name(self):
self.assertEqual( self.assertEqual(
self.response.data['name'], self.student.user.fullname) self.response.data['name'], self.student.fullname)
def test_all_student_submissions_are_loded(self): def test_all_student_submissions_are_loded(self):
self.assertEqual(len(self.submission_list), self.assertEqual(len(self.submission_list),
...@@ -76,40 +77,40 @@ class StudentPageTests(APITestCase): ...@@ -76,40 +77,40 @@ class StudentPageTests(APITestCase):
def test_exam_data_contains_module_reference(self): def test_exam_data_contains_module_reference(self):
self.assertEqual( self.assertEqual(
self.exam_obj["module_reference"], self.exam_obj["module_reference"],
self.student.exam.module_reference) self.student_info.exam.module_reference)
def test_exam_data_contains_total_score(self): def test_exam_data_contains_total_score(self):
self.assertEqual( self.assertEqual(
self.exam_obj["total_score"], self.student.exam.total_score) self.exam_obj["total_score"], self.student_info.exam.total_score)
def test_exam_data_contains_pass_score(self): def test_exam_data_contains_pass_score(self):
self.assertEqual( self.assertEqual(
self.exam_obj["pass_score"], self.student.exam.pass_score) self.exam_obj["pass_score"], self.student_info.exam.pass_score)
def test_exam_data_contains_pass_only_field(self): def test_exam_data_contains_pass_only_field(self):
self.assertEqual( self.assertEqual(
self.exam_obj["pass_only"], self.student.exam.pass_only) self.exam_obj["pass_only"], self.student_info.exam.pass_only)
# Tests concerning submission data # Tests concerning submission data
def test_a_student_submissions_contains_type_name(self): def test_a_student_submissions_contains_type_name(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['typeName'], self.submission_list_first_entry['type']['name'],
self.student.submissions.first().type.name) self.student_info.submissions.first().type.name)
def test_a_student_submissions_contains_type_id(self): def test_a_student_submissions_contains_type_id(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['typeId'], self.submission_list_first_entry['type']['id'],
self.student.submissions.first().type.id) self.student_info.submissions.first().type.id)
def test_submission_data_contains_full_score(self): def test_submission_data_contains_full_score(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['fullScore'], self.submission_list_first_entry['type']['fullScore'],
self.student.submissions.first().type.full_score) self.student_info.submissions.first().type.full_score)
def test_submission_data_contains_feedback_score(self): def test_submission_data_contains_feedback_score(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['score'], self.submission_list_first_entry['feedback']['score'],
self.student.submissions.first().feedback.score) self.student_info.submissions.first().feedback.score)
# We don't want a matriculation number here # We don't want a matriculation number here
def test_matriculation_number_is_not_send(self): def test_matriculation_number_is_not_send(self):
...@@ -148,7 +149,8 @@ class StudentSelfSubmissionsTests(APITestCase): ...@@ -148,7 +149,8 @@ class StudentSelfSubmissionsTests(APITestCase):
}] }]
}) })
self.student = self.test_data['students'][0].student self.student = self.test_data['students'][0]
self.student_info = self.student.student
self.tutor = self.test_data['tutors'][0] self.tutor = self.test_data['tutors'][0]
self.submission = self.test_data['submissions'][0] self.submission = self.test_data['submissions'][0]
self.feedback = self.submission.feedback self.feedback = self.submission.feedback
...@@ -156,7 +158,7 @@ class StudentSelfSubmissionsTests(APITestCase): ...@@ -156,7 +158,7 @@ class StudentSelfSubmissionsTests(APITestCase):
self.request = self.factory.get(reverse('student-submissions')) self.request = self.factory.get(reverse('student-submissions'))
self.view = StudentSelfSubmissionsApiView.as_view() self.view = StudentSelfSubmissionsApiView.as_view()
force_authenticate(self.request, user=self.student.user) force_authenticate(self.request, user=self.student)
self.response = self.view(self.request) self.response = self.view(self.request)
self.submission_list = self.response.data self.submission_list = self.response.data
...@@ -165,33 +167,38 @@ class StudentSelfSubmissionsTests(APITestCase): ...@@ -165,33 +167,38 @@ class StudentSelfSubmissionsTests(APITestCase):
# Tests concerning submission data # Tests concerning submission data
def test_a_student_submissions_contains_type_name(self): def test_a_student_submissions_contains_type_name(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['typeName'], self.submission_list_first_entry['type']['name'],
self.student.submissions.first().type.name) self.student_info.submissions.first().type.name)
def test_a_student_submissions_contains_type_id(self): def test_a_student_submissions_contains_type_id(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['typeId'], self.submission_list_first_entry['type']['id'],
self.student.submissions.first().type.id) self.student_info.submissions.first().type.id)
def test_submission_data_contains_full_score(self): def test_submission_data_contains_full_score(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['fullScore'], self.submission_list_first_entry['type']['fullScore'],
self.student.submissions.first().type.full_score) self.student_info.submissions.first().type.full_score)
def test_submission_data_contains_text(self): def test_submission_data_contains_description(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['text'], self.submission_list_first_entry['type']['description'],
self.student.submissions.first().text) self.student_info.submissions.first().type.description)
def test_submission_data_contains_feedback_score(self): def test_submission_data_contains_solution(self):
self.assertEqual(
self.submission_list_first_entry['type']['solution'],
self.student_info.submissions.first().type.solution)
def test_submission_data_contains_final_status(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['score'], self.submission_list_first_entry['feedback']['isFinal'],
self.student.submissions.first().feedback.score) self.student_info.submissions.first().feedback.is_final)
def test_submission_data_contains_feedback_text(self): def test_submission_data_contains_feedback_score(self):
self.assertEqual( self.assertEqual(
self.submission_list_first_entry['feedback'], self.submission_list_first_entry['feedback']['score'],
self.student.submissions.first().feedback.text) self.student_info.submissions.first().feedback.score)
# We don't want a matriculation number here # We don't want a matriculation number here
def test_matriculation_number_is_not_send(self): def test_matriculation_number_is_not_send(self):
......
...@@ -69,5 +69,6 @@ class StudentPageTests(APITestCase): ...@@ -69,5 +69,6 @@ class StudentPageTests(APITestCase):
self.response.data[0]['submissions'][0]['score']) self.response.data[0]['submissions'][0]['score'])
def test_submissions_full_score_is_included(self): def test_submissions_full_score_is_included(self):
print(self.response.data[0]['submissions'][0])
self.assertEqual(self.student.submissions.first().type.full_score, self.assertEqual(self.student.submissions.first().type.full_score,
self.response.data[0]['submissions'][0]['fullScore']) self.response.data[0]['submissions'][0]['fullScore'])
...@@ -62,7 +62,7 @@ class SubmissionTypeViewTestRetrieve(APITestCase): ...@@ -62,7 +62,7 @@ class SubmissionTypeViewTestRetrieve(APITestCase):
self.assertEqual(self.response.status_code, status.HTTP_200_OK) self.assertEqual(self.response.status_code, status.HTTP_200_OK)
def test_get_id(self): def test_get_id(self):
self.assertEqual(self.pk, self.response.data['typeId']) self.assertEqual(self.pk, self.response.data['id'])
def test_get_sumbission_type_name(self): def test_get_sumbission_type_name(self):
self.assertEqual('Hard question', self.response.data['name']) self.assertEqual('Hard question', self.response.data['name'])
......
...@@ -247,17 +247,13 @@ def init_test_instance(): ...@@ -247,17 +247,13 @@ def init_test_instance():
' asasxasx\n' ' asasxasx\n'
' lorem ipsum und so\n', ' lorem ipsum und so\n',
'type': '02. Merge this or that or maybe even this', 'type': '02. Merge this or that or maybe even this',
'user': 'student01' 'user': 'student01',
}, 'feedback': {
{ 'text': 'Not good!',
'text': 'function blabl\n' 'score': 5,
' on multi lines\n' 'of_tutor': 'tutor01',
' for blabla in bla:\n' 'is_final': True
' arrrgh\n' }
' asasxasx\n'
' lorem ipsum und so\n',
'type': '03. This one exists for the sole purpose to test',
'user': 'student01'
}, },
{ {
'text': 'function blabl\n' 'text': 'function blabl\n'
...@@ -267,7 +263,13 @@ def init_test_instance(): ...@@ -267,7 +263,13 @@ def init_test_instance():
' asasxasx\n' ' asasxasx\n'
' lorem ipsum und so\n', ' lorem ipsum und so\n',
'type': '03. This one exists for the sole purpose to test', 'type': '03. This one exists for the sole purpose to test',
'user': 'student02' 'user': 'student01',
'feedback': {
'text': 'Not good!',
'score': 5,
'of_tutor': 'tutor01',
'is_final': True
}
}, },
]} ]}
) )
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment