diff --git a/server/app/apis/__init__.py b/server/app/apis/__init__.py index 945d9d7dec2750ac5a7e098100fbc15b76e13545..316dc1521a4ee8e6be2bb99f9bd3abfebcef8d60 100644 --- a/server/app/apis/__init__.py +++ b/server/app/apis/__init__.py @@ -79,44 +79,6 @@ def protect_route(allowed_roles=None, allowed_views=None): return decorator -# def text_response(message, code=http_codes.OK): -# return {"message": message}, code - - -# def list_response(items, total=None, code=http_codes.OK): -# if type(items) is not list: -# abort(http_codes.INTERNAL_SERVER_ERROR) -# if not total: -# total = len(items) -# return {"items": items, "count": len(items), "total_count": total}, code - - -# def item_response(item, code=http_codes.OK): -# if isinstance(item, list): -# abort(http_codes.INTERNAL_SERVER_ERROR) -# return item, code - - -# from flask_restx import Api - -# from .alternatives import api as alternative_ns -# from .answers import api as answer_ns -# from .auth import api as auth_ns -# from .codes import api as code_ns -# from .competitions import api as comp_ns -# from .components import api as component_ns -# from .media import api as media_ns -# from .misc import api as misc_ns -# from .questions import api as question_ns -# from .scores import api as score_ns -# from .slides import api as slide_ns -# from .teams import api as team_ns -# from .users import api as user_ns - -# flask_api = Api() - -# flask_api.add_namespace(score_ns, path="/api/competitions/<competition_id>/teams/<team_id>/answers/question_scores") - from flask_smorest import Api flask_api = Api() @@ -133,6 +95,7 @@ def init_api(): from .media import blp as media_blp from .misc import blp as misc_blp from .questions import blp as question_blp + from .scores import blp as score_blp from .slides import blp as slide_blp from .teams import blp as team_blp from .users import blp as user_blp @@ -149,3 +112,4 @@ def init_api(): flask_api.register_blueprint(alternative_blp) flask_api.register_blueprint(component_blp) flask_api.register_blueprint(answer_blp) + flask_api.register_blueprint(score_blp) diff --git a/server/app/apis/scores.py b/server/app/apis/scores.py index 2d303e1c734b5f776334ea2775fdb1b165db3480..c90e4e5c569f917bf20af832e2ca6d5fe444cac4 100644 --- a/server/app/apis/scores.py +++ b/server/app/apis/scores.py @@ -4,53 +4,60 @@ Default route: /api/competitions/<competition_id>/teams/<team_id>/answers/quesit """ import app.database.controller as dbc -from app.apis import item_response, list_response, protect_route -from app.core.dto import QuestionScoreDTO -from app.core.parsers import sentinel -from flask_restx import Resource, reqparse +from app.apis import protect_route +from app.core import ma +from app.core.schemas import BaseSchema, QuestionScoreSchema +from app.database import models +from flask.views import MethodView +from flask_smorest import Blueprint, abort, response -api = QuestionScoreDTO.api -schema = QuestionScoreDTO.schema -list_schema = QuestionScoreDTO.list_schema +from . import http_codes -score_parser_add = reqparse.RequestParser() -score_parser_add.add_argument("score", type=int, required=False, location="json") +blp = Blueprint( + "score", + "score", + url_prefix="/api/competitions/<competition_id>/teams/<team_id>/scores", + description="Operations on scores", +) -score_parser_edit = reqparse.RequestParser() -score_parser_edit.add_argument("score", type=int, default=sentinel, location="json") +class ScoreAddArgsSchema(BaseSchema): + class Meta(BaseSchema.Meta): + model = models.QuestionScore -@api.route("/") -@api.param("competition_id, team_id") -class QuestionScoreList(Resource): + score = ma.auto_field(required=False) + + +@blp.route("") +class QuestionScoreList(MethodView): @protect_route(allowed_roles=["*"], allowed_views=["*"]) + @blp.response(http_codes.OK, QuestionScoreSchema(many=True)) def get(self, competition_id, team_id): """ Gets all question answers that the specified team has given. """ + return dbc.get.question_score_list(competition_id, team_id) - items = dbc.get.question_score_list(competition_id, team_id) - return list_response(list_schema.dump(items)) - -@api.route("/<question_id>") -@api.param("competition_id, team_id, question_id") -class QuestionScores(Resource): +@blp.route("/<question_id>") +class QuestionScores(MethodView): @protect_route(allowed_roles=["*"], allowed_views=["*"]) + @blp.response(http_codes.OK, QuestionScoreSchema) + @blp.alt_response(http_codes.NOT_FOUND, None, description="Cant find answer") def get(self, competition_id, team_id, question_id): - """ Gets the specified question answer. """ - - item = dbc.get.question_score(competition_id, team_id, question_id) - return item_response(schema.dump(item)) + """ Gets the score for the provided team on the provided question. """ + return dbc.get.question_score(competition_id, team_id, question_id) @protect_route(allowed_roles=["*"], allowed_views=["*"]) - def put(self, competition_id, team_id, question_id): + @blp.arguments(ScoreAddArgsSchema) + @blp.response(http_codes.OK, QuestionScoreSchema) + @blp.alt_response(http_codes.NOT_FOUND, None, description="Cant find score") + @blp.alt_response(http_codes.CONFLICT, None, description="Can't add or edit score with provided values") + def put(self, args, competition_id, team_id, question_id): """ Add or edit specified quesiton_answer. """ item = dbc.get.question_score(competition_id, team_id, question_id, required=False) if item is None: - args = score_parser_add.parse_args(strict=True) item = dbc.add.question_score(args.get("score"), question_id, team_id) else: - args = score_parser_edit.parse_args(strict=True) item = dbc.edit.default(item, **args) - return item_response(schema.dump(item)) + return item diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py index a84f9082374bd5c3d2794817f9f8c1a270065c52..2455faac0862b4755b7e2c64d95c070d63c6287a 100644 --- a/server/app/database/__init__.py +++ b/server/app/database/__init__.py @@ -72,19 +72,3 @@ class ExtendedQuery(BaseQuery): pagination = self.paginate(page=pagination_parameters.page, per_page=pagination_parameters.page_size) pagination_parameters.item_count = pagination.total return pagination.items - - -# class Dictionary(TypeDecorator): - -# impl = Text - -# def process_bind_param(self, value, dialect): -# if value is not None: -# value = json.dumps(value) - -# return value - -# def process_result_value(self, value, dialect): -# if value is not None: -# value = json.loads(value) -# return value diff --git a/server/app/database/controller/add.py b/server/app/database/controller/add.py index c62cfefc5cedec583dd06fc422ac7c10cd46e3c2..f8ead2dd3a3fece68d4cb9e46a1488c31826357a 100644 --- a/server/app/database/controller/add.py +++ b/server/app/database/controller/add.py @@ -7,34 +7,18 @@ import os import app.database.controller as dbc from app.apis import http_codes from app.core import db -from app.database.models import ( - Blacklist, - City, - Code, - Competition, - ComponentType, - ImageComponent, - Media, - MediaType, - Question, - QuestionAlternative, - QuestionAlternativeAnswer, - QuestionComponent, - QuestionScore, - QuestionType, - Role, - Slide, - Team, - TextComponent, - User, - ViewType, - Whitelist, -) -from app.database.types import IMAGE_COMPONENT_ID, QUESTION_COMPONENT_ID, TEXT_COMPONENT_ID +from app.database.models import (Blacklist, City, Code, Competition, + ComponentType, ImageComponent, Media, + MediaType, Question, QuestionAlternative, + QuestionAlternativeAnswer, QuestionComponent, + QuestionScore, QuestionType, Role, Slide, + Team, TextComponent, User, ViewType, + Whitelist) +from app.database.types import (IMAGE_COMPONENT_ID, QUESTION_COMPONENT_ID, + TEXT_COMPONENT_ID) from flask import current_app from flask.globals import current_app from flask_smorest import abort - # from flask_restx import abort from PIL import Image from sqlalchemy import exc @@ -268,7 +252,7 @@ def question_alternative(alternative, correct, question_id): def question_score(score, question_id, team_id): """ - Adds a question answer to the specified team + Adds a question score to the specified team and question using the provided arguments. """