summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yaksh/fixtures/marks_header_missing.csv3
-rw-r--r--yaksh/fixtures/marks_header_modified.csv3
-rw-r--r--yaksh/fixtures/marks_invalid_data.csv3
-rw-r--r--yaksh/fixtures/marks_invalid_question_id.csv3
-rw-r--r--yaksh/fixtures/marks_invalid_user.csv3
-rw-r--r--yaksh/fixtures/marks_not_attempted_question.csv3
-rw-r--r--yaksh/fixtures/marks_single_question.csv3
-rw-r--r--yaksh/test_views.py186
-rw-r--r--yaksh/views.py72
9 files changed, 245 insertions, 34 deletions
diff --git a/yaksh/fixtures/marks_header_missing.csv b/yaksh/fixtures/marks_header_missing.csv
new file mode 100644
index 0000000..8c3a747
--- /dev/null
+++ b/yaksh/fixtures/marks_header_missing.csv
@@ -0,0 +1,3 @@
+username,Q-1212-Dummy1-1.0-marks
+student1,0.9
+student2,1
diff --git a/yaksh/fixtures/marks_header_modified.csv b/yaksh/fixtures/marks_header_modified.csv
new file mode 100644
index 0000000..08ba31d
--- /dev/null
+++ b/yaksh/fixtures/marks_header_modified.csv
@@ -0,0 +1,3 @@
+username,Q-1212-Dummmy1-1.0-marks,Q-1212-Dummy1-comments,Q-1213-Dummy2-1.0-marks,Q-1213-Dummy2-comments
+student1,0.75,fine work,1,not nice
+student2,1,good work,0,not okay
diff --git a/yaksh/fixtures/marks_invalid_data.csv b/yaksh/fixtures/marks_invalid_data.csv
new file mode 100644
index 0000000..44fb2bb
--- /dev/null
+++ b/yaksh/fixtures/marks_invalid_data.csv
@@ -0,0 +1,3 @@
+username,Q-1212-Dummy1-1.0-marks,Q-1212-Dummy1-comments,Q-1213-Dummy2-1.0-marks,Q-1213-Dummy2-comments
+student1,NA,good work,1,nice
+student2,1,good work,0,bad
diff --git a/yaksh/fixtures/marks_invalid_question_id.csv b/yaksh/fixtures/marks_invalid_question_id.csv
new file mode 100644
index 0000000..eb1d921
--- /dev/null
+++ b/yaksh/fixtures/marks_invalid_question_id.csv
@@ -0,0 +1,3 @@
+username,Q-12112-Dummy1-1.0-marks,Q-1212-Dummy1-comments,Q-1213-Dummy2-1.0-marks,Q-1213-Dummy2-comments
+student1,1,good work,1,nice
+student2,1,good work,0,bad
diff --git a/yaksh/fixtures/marks_invalid_user.csv b/yaksh/fixtures/marks_invalid_user.csv
new file mode 100644
index 0000000..bd31071
--- /dev/null
+++ b/yaksh/fixtures/marks_invalid_user.csv
@@ -0,0 +1,3 @@
+username,Q-1212-Dummy1-1.0-marks,Q-1212-Dummy1-comments,Q-1213-Dummy2-1.0-marks,Q-1213-Dummy2-comments
+student1,1,good work,1,nice
+student452,1,good work,0,bad
diff --git a/yaksh/fixtures/marks_not_attempted_question.csv b/yaksh/fixtures/marks_not_attempted_question.csv
new file mode 100644
index 0000000..3c3e2e7
--- /dev/null
+++ b/yaksh/fixtures/marks_not_attempted_question.csv
@@ -0,0 +1,3 @@
+username,Q-1212-Dummy1-1.0-marks,Q-1212-Dummy1-comments,Q-1213-Dummy2-1.0-marks,Q-1213-Dummy2-comments
+student1,1,good work,1,nice
+student2,0.3,very good,1,good
diff --git a/yaksh/fixtures/marks_single_question.csv b/yaksh/fixtures/marks_single_question.csv
new file mode 100644
index 0000000..9677730
--- /dev/null
+++ b/yaksh/fixtures/marks_single_question.csv
@@ -0,0 +1,3 @@
+username,Q-1212-Dummy1-1.0-marks,Q-1212-Dummy1-comments
+student1,0.5,okay work
+student2,1,good work
diff --git a/yaksh/test_views.py b/yaksh/test_views.py
index e87686c..ea3858e 100644
--- a/yaksh/test_views.py
+++ b/yaksh/test_views.py
@@ -2672,14 +2672,23 @@ class TestUploadMarks(TestCase):
question=self.question2, answer="answer2",
correct=False, error=json.dumps([]), marks=0
)
+ self.answer12 = Answer(
+ question=self.question1, answer="answer12",
+ correct=False, error=json.dumps([]), marks=0
+ )
self.answer1.save()
+ self.answer12.save()
self.answer2.save()
self.ans_paper1.answers.add(self.answer1)
self.ans_paper1.answers.add(self.answer2)
+ self.ans_paper2.answers.add(self.answer12)
self.ans_paper1.questions_answered.add(self.question1)
self.ans_paper1.questions_answered.add(self.question2)
+ self.ans_paper2.questions_answered.add(self.question1)
self.ans_paper1.questions.add(self.question1)
self.ans_paper1.questions.add(self.question2)
+ self.ans_paper2.questions.add(self.question1)
+ self.ans_paper2.questions.add(self.question2)
def tearDown(self):
self.client.logout()
@@ -2696,6 +2705,181 @@ class TestUploadMarks(TestCase):
self.question2.delete()
self.mod_group.delete()
+ def test_upload_users_marks_not_attempted_question(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_not_attempted_question.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+ ans_paper = AnswerPaper.objects.get(user=self.student2,
+ question_paper=self.question_paper,
+ course=self.course)
+ self.assertEqual(ans_paper.marks_obtained, 1.3)
+ answer = Answer.objects.get(answer='answer12')
+ self.assertEqual(answer.comment.strip(), 'very good')
+
+ def test_upload_users_marks_invalid_question_id(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_invalid_question_id.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+
+ def test_upload_users_marks_invalid_user(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_invalid_user.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+
+ def test_upload_users_marks_invalid_data(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_invalid_data.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+
+ def test_upload_users_marks_headers_missing(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_header_missing.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+ ans_paper = AnswerPaper.objects.get(user=self.student1,
+ question_paper=self.question_paper,
+ course=self.course)
+ self.assertEqual(ans_paper.marks_obtained, 0.9)
+
+ def test_upload_users_marks_headers_modified(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_header_modified.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+ answer = Answer.objects.get(answer='answer1')
+ self.assertEqual(answer.comment.strip(), 'fine work')
+ self.assertNotEqual(answer.marks, 0.75)
+ answer = Answer.objects.get(answer='answer2')
+ self.assertEqual(answer.comment.strip(), 'not nice')
+
+ def test_upload_users_marks_csv_single_question(self):
+ # Given
+ self.client.login(
+ username=self.teacher.username,
+ password='teacher'
+ )
+ csv_file_path = os.path.join(FIXTURES_DIR_PATH,
+ "marks_single_question.csv")
+ csv_file = open(csv_file_path, 'rb')
+ upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
+
+ # When
+ response = self.client.post(
+ reverse('yaksh:upload_marks',
+ kwargs={'course_id': self.course.id,
+ 'questionpaper_id': self.question_paper.id}),
+ data={'csv_file': upload_file})
+ csv_file.close()
+
+ # Then
+ self.assertEqual(response.status_code, 302)
+ ans_paper = AnswerPaper.objects.get(user=self.student1,
+ question_paper=self.question_paper,
+ course=self.course)
+ self.assertEqual(ans_paper.marks_obtained, 0.5)
+ answer = Answer.objects.get(answer='answer1')
+ self.assertEqual(answer.comment.strip(), 'okay work')
+
def test_upload_users_with_correct_csv(self):
# Given
self.client.login(
@@ -2705,7 +2889,6 @@ class TestUploadMarks(TestCase):
csv_file_path = os.path.join(FIXTURES_DIR_PATH, "marks_correct.csv")
csv_file = open(csv_file_path, 'rb')
upload_file = SimpleUploadedFile(csv_file_path, csv_file.read())
- previous_total = self.ans_paper1.marks_obtained
# When
response = self.client.post(
@@ -2717,7 +2900,6 @@ class TestUploadMarks(TestCase):
# Then
self.assertEqual(response.status_code, 302)
- self.assertEqual(previous_total, 0)
ans_paper = AnswerPaper.objects.get(user=self.student1,
question_paper=self.question_paper,
course=self.course)
diff --git a/yaksh/views.py b/yaksh/views.py
index 7a4810c..eb2cc31 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -4073,12 +4073,8 @@ def upload_marks(request, course_id, questionpaper_id):
except TypeError:
messages.warning(request, "Bad CSV file")
return redirect('yaksh:monitor', quiz.id, course_id)
- user_ids, question_ids = _get_header_info(reader)
- csv_file.seek(0)
- reader = csv.DictReader(csv_file.read().decode('utf-8').splitlines(),
- dialect=dialect)
- _read_marks_csv(reader, course, question_paper, user_ids, question_ids)
- messages.warning(request, "Marks uploaded!")
+ question_ids = _get_header_info(reader)
+ _read_marks_csv(request, reader, course, question_paper, question_ids)
return redirect('yaksh:monitor', quiz.id, course_id)
@@ -4090,43 +4086,55 @@ def _get_header_info(reader):
qid = int(field.split('-')[1])
if qid not in question_ids:
question_ids.append(qid)
- for row in reader:
- username = row['username']
- user = User.objects.filter(username=username).first()
- if not user:
- pass
- user_ids.append(user.id)
- return user_ids, question_ids
+ return question_ids
-def _read_marks_csv(reader, course, question_paper, user_ids, question_ids):
- answerpapers = question_paper.answerpaper_set.filter(course=course,
- user_id__in=user_ids)
+def _read_marks_csv(request, reader, course, question_paper, question_ids):
+ messages.info(request, 'Marks Uploaded!')
for row in reader:
username = row['username']
user = User.objects.filter(username=username).first()
- if not user:
- pass
- answerpaper = answerpapers.get(user=user)
+ if user:
+ answerpapers = question_paper.answerpaper_set.filter(course=course,
+ user_id=user.id)
+ else:
+ messages.info(request, '{0} user not found!'.format(username))
+ continue
+ answerpaper = answerpapers.last()
+ if not answerpaper:
+ messages.info(request, '{0} has no answerpaper!'.format(username))
+ continue
answers = answerpaper.answers.all()
- answered = answerpaper.questions_answered.all().values_list('id',
- flat=True)
+ questions = answerpaper.questions.all().values_list('id', flat=True)
for qid in question_ids:
question = Question.objects.filter(id=qid).first()
if not question:
- pass
- if qid in answered:
+ messages.info(request,
+ '{0} is an invalid question id!'.format(qid))
+ continue
+ if qid in questions:
answer = answers.filter(question_id=qid).last()
if not answer:
- pass
- answer.set_marks(
- float(row['Q-{0}-{1}-{2}-marks'.format(
- qid, question.summary, question.points)])
- )
- answer.set_comment(
- row['Q-{0}-{1}-comments'.format(
- qid, question.summary, question.points)]
- )
+ answer = Answer(question_id=qid, marks=0, correct=False,
+ answer='Created During Marks Update!',
+ error=json.dumps([]))
+ answer.save()
+ answerpaper.answers.add(answer)
+ key1 = 'Q-{0}-{1}-{2}-marks'.format(qid, question.summary,
+ question.points)
+ key2 = 'Q-{0}-{1}-comments'.format(qid, question.summary,
+ question.points)
+ if key1 in reader.fieldnames:
+ try:
+ answer.set_marks(float(row[key1]))
+ except ValueError:
+ messages.info(request,
+ '{0} invalid marks!'.format(row[key1]))
+ if key2 in reader.fieldnames:
+ answer.set_comment(row[key2])
answer.save()
answerpaper.update_marks(state='completed')
answerpaper.save()
+ messages.info(request,
+ 'Updated successfully for user: {0}, question: {1}'.format(
+ username, question.summary))