Commit 56c0edec by Stephen Sanchez

My first pass at populate the submission API.

parent 7a722780
......@@ -10,8 +10,14 @@ might be tricky with XML import based courses).
"""
def create_evaluation(submission_id, score, rubric):
pass
def get_evaluations(submission_id):
pass
def get_submission_to_evaluate(student_item, scorer_student_id):
pass
......@@ -2,20 +2,61 @@
Public interface for the submissions app.
"""
from datetime import datetime
from submissions.serializers import SubmissionSerializer
from submissions.models import Submission, StudentItem, SubmissionStruct
def create_submission(student_item, answer, submitted_at=None):
# score could be an optional param in the future.
pass
student_item = _get_student_item(student_item)
submitted_at = submitted_at if submitted_at else datetime.now()
if student_item:
submissions = Submission.objects.filter(student_item=student_item).order_by("submitted_at")[:0]
attempt_number = submissions[0].attempt_number if submissions else 1
submission = Submission.objects.create(
student_item=student_item,
submitted_at=submitted_at,
answer=answer,
attempt_number=attempt_number,
)
return SubmissionStruct(**SubmissionSerializer(submission).data)
def get_submissions(student_item, limit=None):
pass
student_item = _get_student_item(student_item)
item_response = StudentItem.objects.get_or_create(
student_id=student_item.student_id,
course_id=student_item.course_id,
item_id=student_item.item_id,
item_type=student_item.item_type,
)
if limit:
submission_models = Submission.objects.filter(student_item=item_response[0])[:limit]
else:
submission_models = Submission.objects.filter(student_item=item_response[0])
return [SubmissionStruct(**SubmissionSerializer(submission).data) for submission in submission_models]
def get_score(student_item):
pass
def get_scores(course_id, student_id, types=None):
pass
def set_score(student_item):
pass
def _get_student_item(student_item):
student_items = StudentItem.objects.filter(
item_id=student_item.item_id,
student_id=student_item.student_id,
course_id=student_item.course_id,
)
return student_items[0] if student_items else None
\ No newline at end of file
......@@ -5,8 +5,8 @@ workflows, ORA, etc. So the flow is this:
Student submission:
* XBlock creates a Submission
* submissions app sends a general notification that a submission has happened
* openresponse can listen for that signal if it wants, or query itself on demand
* when openresponse is satistifed that it has collected enough information to
* openassessment can listen for that signal if it wants, or query itself on demand
* when openassessment is satisfied that it has collected enough information to
score the student, it will push that score information back to this app.
* when the LMS wants to know what raw scores a student has, it calls this app.
......@@ -15,9 +15,13 @@ Things to consider probably aren't worth the extra effort/complexity in the MVP:
* Version ID (this doesn't work until split-mongostore comes into being)
"""
from collections import namedtuple
from django.db import models
from django.utils.timezone import now
StudentItemStruct = namedtuple("StudentItemStruct", "student_id course_id item_id item_type")
class StudentItem(models.Model):
"""Represents a single item for a single course for a single user.
......@@ -42,11 +46,10 @@ class StudentItem(models.Model):
unique_together = (
# For integrity reasons, and looking up all of a student's items
("course_id", "student_id", "item_id"),
# Composite index for getting information across a course
("course_id", "item_id"),
)
SubmissionStruct = namedtuple("SubmissionStruct", "student_item attempt_number submitted_at created_at answer")
class Submission(models.Model):
"""A single response by a student for a given problem in a given course.
......
from rest_framework import serializers
from submissions.models import StudentItem, Submission, Score
class StudentItemSerializer(serializers.ModelSerializer):
class Meta:
model = StudentItem
fields = ('student_id', 'course_id', 'item_id', 'item_type')
class SubmissionSerializer(serializers.ModelSerializer):
class Meta:
model = Submission
fields = ('student_item', 'attempt_number', 'submitted_at', 'created_at', 'answer')
class ScoreSerializer(serializers.ModelSerializer):
class Meta:
model = Score
fields = ('student_item', 'submission', 'points_earned', 'points_possible', 'created_at')
from django.test import TestCase
from submissions.models import StudentItem, StudentItemStruct
from submissions.api import create_submission, get_submissions
STUDENT_ITEM = StudentItemStruct(
student_id="Tim",
course_id="Demo_Course",
item_id="item_one",
item_type="Peer_Submission"
)
class TestApi(TestCase):
def setUp(self):
StudentItem.objects.create(
student_id=STUDENT_ITEM.student_id,
course_id=STUDENT_ITEM.course_id,
item_id=STUDENT_ITEM.item_id,
item_type=STUDENT_ITEM.student_id
)
def test_create_submission(self):
submission = create_submission(STUDENT_ITEM, "this is my answer!")
self._assert_submission(submission, "this is my answer!", 1, 1)
def test_get_submission(self):
create_submission(STUDENT_ITEM, "this is my answer!")
create_submission(STUDENT_ITEM, "this is my other answer!")
submissions = get_submissions(STUDENT_ITEM)
self._assert_submission(submissions[0], "this is my answer!", 1, 1)
self._assert_submission(submissions[1], "this is my other answer!", 1, 1)
def _assert_submission(self, submission, expected_answer, expected_item, expected_attempt):
self.assertIsNotNone(submission)
self.assertEqual(submission.answer, expected_answer)
self.assertEqual(submission.student_item, expected_item)
self.assertEqual(submission.attempt_number, expected_attempt)
\ No newline at end of file
......@@ -3,3 +3,4 @@
# Third Party Requirements
django==1.4.8
djangorestframework==2.3.5
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment