Skip to content
Snippets Groups Projects
Commit 79decc4b authored by Victor Löfgren's avatar Victor Löfgren
Browse files

Add alternatives api

parent edb1dbfb
No related branches found
No related tags found
1 merge request!161Resolve "replace-restx-with-smorest"
...@@ -132,6 +132,7 @@ flask_api = Api() ...@@ -132,6 +132,7 @@ flask_api = Api()
def init_api(): def init_api():
from .alternatives import blp as alternative_blp
from .auth import blp as auth_blp from .auth import blp as auth_blp
from .codes import blp as code_blp from .codes import blp as code_blp
from .competitions import blp as competition_blp from .competitions import blp as competition_blp
...@@ -151,3 +152,4 @@ def init_api(): ...@@ -151,3 +152,4 @@ def init_api():
flask_api.register_blueprint(question_blp) flask_api.register_blueprint(question_blp)
flask_api.register_blueprint(team_blp) flask_api.register_blueprint(team_blp)
flask_api.register_blueprint(code_blp) flask_api.register_blueprint(code_blp)
flask_api.register_blueprint(alternative_blp)
...@@ -3,79 +3,84 @@ All API calls concerning question alternatives. ...@@ -3,79 +3,84 @@ All API calls concerning question alternatives.
Default route: /api/competitions/<competition_id>/slides/<slide_id>/questions/<question_id>/alternatives Default route: /api/competitions/<competition_id>/slides/<slide_id>/questions/<question_id>/alternatives
""" """
from os import abort
import app.core.http_codes as codes
import app.database.controller as dbc import app.database.controller as dbc
from app.apis import item_response, list_response, protect_route from app.apis import protect_route
from app.core.dto import QuestionAlternativeDTO from app.core import ma
from app.core.parsers import sentinel from app.core.schemas import BaseSchema, QuestionAlternativeSchema
from app.database import models
from app.database.models import Question, QuestionAlternative from app.database.models import Question, QuestionAlternative
from flask_restx import Resource, reqparse from flask.views import MethodView
from flask_smorest import Blueprint, abort
api = QuestionAlternativeDTO.api from . import http_codes
schema = QuestionAlternativeDTO.schema
list_schema = QuestionAlternativeDTO.list_schema
alternative_parser_add = reqparse.RequestParser() blp = Blueprint(
alternative_parser_add.add_argument("alternative", type=str, default="", location="json") "alternative",
alternative_parser_add.add_argument("correct", type=str, default="", location="json") "alternative",
url_prefix="/api/competitions/<competition_id>/slides/<slide_id>/questions/<question_id>/alternatives",
description="Adding, updating, deleting and copy alternatives",
)
alternative_parser_edit = reqparse.RequestParser()
alternative_parser_edit.add_argument("alternative", type=str, default=sentinel, location="json")
alternative_parser_edit.add_argument("alternative_order", type=int, default=sentinel, location="json")
alternative_parser_edit.add_argument("correct", type=str, default=sentinel, location="json")
alternative_parser_edit.add_argument("correct_order", type=int, default=sentinel, location="json")
class AlternativeAddArgsSchema(BaseSchema):
class Meta(BaseSchema.Meta):
model = models.QuestionAlternative
@api.route("") alternative = ma.auto_field(required=False, missing="")
@api.param("competition_id, slide_id, question_id") correct = ma.auto_field(required=False, missing="")
class QuestionAlternativeList(Resource):
class AlternativeEditArgsSchema(BaseSchema):
class Meta(BaseSchema.Meta):
model = models.QuestionAlternative
alternative = ma.auto_field(required=False)
alternative_order = ma.auto_field(required=False, missing=None)
correct = ma.auto_field(required=False)
correct_order = ma.auto_field(required=False, missing=None)
@blp.route("")
class Alternatives(MethodView):
@protect_route(allowed_roles=["*"], allowed_views=["*"]) @protect_route(allowed_roles=["*"], allowed_views=["*"])
@blp.response(http_codes.OK, QuestionAlternativeSchema(many=True))
def get(self, competition_id, slide_id, question_id): def get(self, competition_id, slide_id, question_id):
""" Gets the all question alternatives to the specified question. """ """ Gets the all question alternatives to the specified question. """
return dbc.get.question_alternative_list(competition_id, slide_id, question_id)
items = dbc.get.question_alternative_list(
competition_id,
slide_id,
question_id,
)
return list_response(list_schema.dump(items))
@protect_route(allowed_roles=["*"]) @protect_route(allowed_roles=["*"])
def post(self, competition_id, slide_id, question_id): @blp.arguments(AlternativeAddArgsSchema)
@blp.response(http_codes.OK, QuestionAlternativeSchema)
@blp.alt_response(http_codes.CONFLICT, None, description="Could not add alternative")
def post(self, args, competition_id, slide_id, question_id):
""" """
Posts a new question alternative to the specified Posts a new question alternative to the specified
question using the provided arguments. question using the provided arguments.
""" """
return dbc.add.question_alternative(**args, question_id=question_id)
args = alternative_parser_add.parse_args(strict=True)
item = dbc.add.question_alternative(**args, question_id=question_id)
return item_response(schema.dump(item))
@api.route("/<alternative_id>") @blp.route("/<alternative_id>")
@api.param("competition_id, slide_id, question_id, alternative_id") class QuestionAlternatives(MethodView):
class QuestionAlternatives(Resource):
@protect_route(allowed_roles=["*"], allowed_views=["*"]) @protect_route(allowed_roles=["*"], allowed_views=["*"])
@blp.response(http_codes.OK, QuestionAlternativeSchema)
@blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find alternative")
def get(self, competition_id, slide_id, question_id, alternative_id): def get(self, competition_id, slide_id, question_id, alternative_id):
""" Gets the specified question alternative. """ """ Gets the specified question alternative. """
return dbc.get.question_alternative(competition_id, slide_id, question_id, alternative_id)
items = dbc.get.question_alternative(
competition_id,
slide_id,
question_id,
alternative_id,
)
return item_response(schema.dump(items))
@protect_route(allowed_roles=["*"]) @protect_route(allowed_roles=["*"])
def put(self, competition_id, slide_id, question_id, alternative_id): @blp.arguments(AlternativeEditArgsSchema)
@blp.response(http_codes.OK, QuestionAlternativeSchema)
@blp.alt_response(http_codes.BAD_REQUEST, None, description="Paramters to edit alternative with is incorrect")
@blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find alternative")
@blp.alt_response(http_codes.CONFLICT, None, description="Could not edit alternative with the given values")
def put(self, args, competition_id, slide_id, question_id, alternative_id):
""" """
Edits the specified question alternative using the provided arguments. Edits the specified question alternative using the provided arguments.
""" """
args = alternative_parser_edit.parse_args(strict=True)
item = dbc.get.question_alternative( item = dbc.get.question_alternative(
competition_id, competition_id,
slide_id, slide_id,
...@@ -84,9 +89,12 @@ class QuestionAlternatives(Resource): ...@@ -84,9 +89,12 @@ class QuestionAlternatives(Resource):
) )
new_alternative_order = args.pop("alternative_order") new_alternative_order = args.pop("alternative_order")
if new_alternative_order is not sentinel and item.alternative_order != new_alternative_order: if new_alternative_order is not None and item.alternative_order != new_alternative_order:
if not (0 <= new_alternative_order < dbc.utils.count(QuestionAlternative, {"question_id": question_id})): if not (0 <= new_alternative_order < dbc.utils.count(QuestionAlternative, {"question_id": question_id})):
abort(codes.BAD_REQUEST, f"Cant change to invalid slide order '{new_alternative_order}'") abort(
http_codes.BAD_REQUEST,
message=f"Kan inte ändra till ogiltigt sidordning '{new_alternative_order}'",
)
item_question = dbc.get.one(Question, question_id) item_question = dbc.get.one(Question, question_id)
dbc.utils.move_order( dbc.utils.move_order(
...@@ -94,25 +102,20 @@ class QuestionAlternatives(Resource): ...@@ -94,25 +102,20 @@ class QuestionAlternatives(Resource):
) )
new_correct_order = args.pop("correct_order") new_correct_order = args.pop("correct_order")
if new_correct_order is not sentinel and item.correct_order != new_correct_order: if new_correct_order is not None and item.correct_order != new_correct_order:
if not (0 <= new_correct_order < dbc.utils.count(QuestionAlternative, {"question_id": question_id})): if not (0 <= new_correct_order < dbc.utils.count(QuestionAlternative, {"question_id": question_id})):
abort(codes.BAD_REQUEST, f"Cant change to invalid slide order '{new_correct_order}'") abort(http_codes.BAD_REQUEST, message=f"Kan inte ändra till ogiltigt sidordning '{new_correct_order}'")
item_question = dbc.get.one(Question, question_id) item_question = dbc.get.one(Question, question_id)
dbc.utils.move_order(item_question.alternatives, "correct_order", item.correct_order, new_correct_order) dbc.utils.move_order(item_question.alternatives, "correct_order", item.correct_order, new_correct_order)
item = dbc.edit.default(item, **args) return dbc.edit.default(item, **args)
return item_response(schema.dump(item))
@protect_route(allowed_roles=["*"]) @protect_route(allowed_roles=["*"])
@blp.response(http_codes.NO_CONTENT, None)
@blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find alternative")
@blp.alt_response(http_codes.CONFLICT, None, description="Could not delete alternative")
def delete(self, competition_id, slide_id, question_id, alternative_id): def delete(self, competition_id, slide_id, question_id, alternative_id):
""" Deletes the specified question alternative. """ """ Deletes the specified question alternative. """
dbc.delete.default(dbc.get.question_alternative(competition_id, slide_id, question_id, alternative_id))
item = dbc.get.question_alternative( return None
competition_id,
slide_id,
question_id,
alternative_id,
)
dbc.delete.default(item)
return {}, codes.NO_CONTENT
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment