Skip to content
Snippets Groups Projects
Commit ab3c2799 authored by jtimotei's avatar jtimotei
Browse files

Merge branch 'mc-option-inheritance' into 'develop'

MultipleChoiceOption is a widget, /exams API call now returns checkbox data

See merge request !11
parents 565c3bc2 66d8cc3a
No related branches found
No related tags found
1 merge request!11MultipleChoiceOption is a widget, /exams API call now returns checkbox data
Pipeline #17678 passed
""" empty message """empty message
Revision ID: f97aa3c73453 Revision ID: b46a2994605b
Revises: 4204f4a83863 Revises: 4204f4a83863
Create Date: 2019-05-15 15:41:56.615076
""" """
from alembic import op from alembic import op
...@@ -9,25 +10,28 @@ import sqlalchemy as sa ...@@ -9,25 +10,28 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'f97aa3c73453' revision = 'b46a2994605b'
down_revision = '4204f4a83863' down_revision = '4204f4a83863'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('mc_option', op.create_table('mc_option',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('x', sa.Integer(), nullable=False),
sa.Column('y', sa.Integer(), nullable=False),
sa.Column('label', sa.String(), nullable=True), sa.Column('label', sa.String(), nullable=True),
sa.Column('problem_id', sa.Integer(), nullable=False), sa.Column('problem_id', sa.Integer(), nullable=False),
sa.Column('feedback_id', sa.Integer(), nullable=True), sa.Column('feedback_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['feedback_id'], ['feedback_option.id'], ), sa.ForeignKeyConstraint(['feedback_id'], ['feedback_option.id'], ),
sa.ForeignKeyConstraint(['problem_id'], ['solution.id'], ), sa.ForeignKeyConstraint(['id'], ['widget.id'], ),
sa.ForeignKeyConstraint(['problem_id'], ['problem.id'], ),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
) )
# ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('mc_option') op.drop_table('mc_option')
# ### end Alembic commands ###
...@@ -154,7 +154,20 @@ class Exams(Resource): ...@@ -154,7 +154,20 @@ class Exams(Resource):
'width': prob.widget.width, 'width': prob.widget.width,
'height': prob.widget.height, 'height': prob.widget.height,
}, },
'graded': any([sol.graded_by is not None for sol in prob.solutions]) 'graded': any([sol.graded_by is not None for sol in prob.solutions]),
'mc_options': [
{
'id': mc_option.id,
'label': mc_option.label,
'problem_id': mc_option.problem_id,
'feedback_id': mc_option.feedback_id,
'widget': {
'name': mc_option.name,
'x': mc_option.x,
'y': mc_option.y
}
} for mc_option in prob.mc_options
]
} for prob in exam.problems # Sorted by prob.id } for prob in exam.problems # Sorted by prob.id
], ],
'widgets': [ 'widgets': [
......
...@@ -3,7 +3,7 @@ from flask_restful import Resource, reqparse ...@@ -3,7 +3,7 @@ from flask_restful import Resource, reqparse
from ..database import db, MultipleChoiceOption from ..database import db, MultipleChoiceOption
def set_mc_data(mc_entry, x, y, problem_id, feedback_id, label): def set_mc_data(mc_entry, name, x, y, mc_type, problem_id, feedback_id, label):
"""Sets the data of a MultipleChoiceOption ORM object. """Sets the data of a MultipleChoiceOption ORM object.
Parameters: Parameters:
...@@ -15,8 +15,10 @@ def set_mc_data(mc_entry, x, y, problem_id, feedback_id, label): ...@@ -15,8 +15,10 @@ def set_mc_data(mc_entry, x, y, problem_id, feedback_id, label):
feedback_id: the feedback the MultipleChoiceOption refers to feedback_id: the feedback the MultipleChoiceOption refers to
label: label for the checkbox that this MultipleChoiceOption represents label: label for the checkbox that this MultipleChoiceOption represents
""" """
mc_entry.name = name
mc_entry.x = x mc_entry.x = x
mc_entry.y = y mc_entry.y = y
mc_entry.type = mc_type
mc_entry.problem_id = problem_id mc_entry.problem_id = problem_id
mc_entry.feedback_id = feedback_id mc_entry.feedback_id = feedback_id
mc_entry.label = label mc_entry.label = label
...@@ -27,6 +29,7 @@ class MultipleChoice(Resource): ...@@ -27,6 +29,7 @@ class MultipleChoice(Resource):
put_parser = reqparse.RequestParser() put_parser = reqparse.RequestParser()
# Arguments that have to be supplied in the request body # Arguments that have to be supplied in the request body
put_parser.add_argument('name', type=str, required=True)
put_parser.add_argument('x', type=int, required=True) put_parser.add_argument('x', type=int, required=True)
put_parser.add_argument('y', type=int, required=True) put_parser.add_argument('y', type=int, required=True)
put_parser.add_argument('label', type=str, required=False) put_parser.add_argument('label', type=str, required=False)
...@@ -47,16 +50,20 @@ class MultipleChoice(Resource): ...@@ -47,16 +50,20 @@ class MultipleChoice(Resource):
args = self.put_parser.parse_args() args = self.put_parser.parse_args()
# Get request arguments # Get request arguments
name = args['name']
x = args['x'] x = args['x']
y = args['y'] y = args['y']
label = args['label'] label = args['label']
problem_id = args['problem_id'] problem_id = args['problem_id']
feedback_id = args['feedback_id'] feedback_id = args['feedback_id']
# TODO: Set type here or add to request?
mc_type = 'mcq_widget'
if not id: if not id:
# Insert new entry into the database # Insert new entry into the database
mc_entry = MultipleChoiceOption() mc_entry = MultipleChoiceOption()
set_mc_data(mc_entry, x, y, problem_id, feedback_id, label) set_mc_data(mc_entry, name, x, y, mc_type, problem_id, feedback_id, label)
db.session.add(mc_entry) db.session.add(mc_entry)
db.session.commit() db.session.commit()
...@@ -69,7 +76,7 @@ class MultipleChoice(Resource): ...@@ -69,7 +76,7 @@ class MultipleChoice(Resource):
if not mc_entry: if not mc_entry:
return dict(status=404, message=f"Multiple choice question with id {id} does not exist"), 404 return dict(status=404, message=f"Multiple choice question with id {id} does not exist"), 404
set_mc_data(mc_entry, x, y, problem_id, feedback_id, label) set_mc_data(mc_entry, name, x, y, mc_type, problem_id, feedback_id, label)
db.session.commit() db.session.commit()
return dict(status=200, message=f'Multiple choice question with id {id} updated'), 200 return dict(status=200, message=f'Multiple choice question with id {id} updated'), 200
...@@ -88,17 +95,22 @@ class MultipleChoice(Resource): ...@@ -88,17 +95,22 @@ class MultipleChoice(Resource):
mult_choice = MultipleChoiceOption.query.get(id) mult_choice = MultipleChoiceOption.query.get(id)
if not mult_choice: if not mult_choice:
return dict(status=404, message='Multiple choice question does not exist.'), 404 return dict(status=404, message=f'Multiple choice question with id {id} does not exist.'), 404
json = { json = {
"id": mult_choice.id, 'id': mult_choice.id,
"x": mult_choice.x, 'name': mult_choice.name,
"y": mult_choice.y, 'x': mult_choice.x,
"problem_id": mult_choice.problem_id, 'y': mult_choice.y,
"feedback_id": mult_choice.feedback_id 'type': mult_choice.type,
'problem_id': mult_choice.problem_id
} }
# Nullable database fields
if mult_choice.label: if mult_choice.label:
json['label'] = mult_choice.label json['label'] = mult_choice.label
if mult_choice.feedback_id:
json['feedback_id'] = mult_choice.feedback_id
return json return json
...@@ -98,6 +98,7 @@ class Problem(db.Model): ...@@ -98,6 +98,7 @@ class Problem(db.Model):
exam_id = Column(Integer, ForeignKey('exam.id'), nullable=False) exam_id = Column(Integer, ForeignKey('exam.id'), nullable=False)
feedback_options = db.relationship('FeedbackOption', backref='problem', order_by='FeedbackOption.id', lazy=True) feedback_options = db.relationship('FeedbackOption', backref='problem', order_by='FeedbackOption.id', lazy=True)
solutions = db.relationship('Solution', backref='problem', lazy=True) solutions = db.relationship('Solution', backref='problem', lazy=True)
mc_options = db.relationship('MultipleChoiceOption', backref='problem', lazy=True)
widget = db.relationship('ProblemWidget', backref='problem', uselist=False, lazy=True) widget = db.relationship('ProblemWidget', backref='problem', uselist=False, lazy=True)
...@@ -160,17 +161,18 @@ class Widget(db.Model): ...@@ -160,17 +161,18 @@ class Widget(db.Model):
} }
class MultipleChoiceOption(db.Model): class MultipleChoiceOption(Widget):
__tablename__ = 'mc_option' __tablename__ = 'mc_option'
id = Column(Integer, primary_key=True, autoincrement=True) id = Column(Integer, ForeignKey('widget.id'), primary_key=True, autoincrement=True)
x = Column(Integer, nullable=False)
y = Column(Integer, nullable=False)
label = Column(String, nullable=True) label = Column(String, nullable=True)
problem_id = Column(Integer, ForeignKey('problem.id'), nullable=False) problem_id = Column(Integer, ForeignKey('problem.id'), nullable=False)
feedback_id = Column(Integer, ForeignKey('feedback_option.id'), nullable=True) feedback_id = Column(Integer, ForeignKey('feedback_option.id'), nullable=True)
__mapper_args__ = {
'polymorphic_identity': 'mcq_widget'
}
class ExamWidget(Widget): class ExamWidget(Widget):
__tablename__ = 'exam_widget' __tablename__ = 'exam_widget'
......
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