Skip to content
Snippets Groups Projects
Commit 0d22489f authored by Carl Schönfelder's avatar Carl Schönfelder
Browse files

Resolve "Improve competition-api"

parent f73bcb4d
No related branches found
No related tags found
1 merge request!40Resolve "Improve competition-api"
Pipeline #38628 passed
......@@ -40,9 +40,15 @@ from flask_restx import Api
from .auth import api as auth_ns
from .competitions import api as comp_ns
from .misc import api as misc_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(misc_ns, path="/api/misc")
flask_api.add_namespace(user_ns, path="/api/users")
flask_api.add_namespace(auth_ns, path="/api/auth")
flask_api.add_namespace(comp_ns, path="/api/competitions")
flask_api.add_namespace(slide_ns, path="/api/competitions/<CID>/slides")
flask_api.add_namespace(team_ns, path="/api/competitions/<CID>/teams")
......@@ -9,8 +9,7 @@ from flask_restx import Resource, reqparse
api = CompetitionDTO.api
competition_model = CompetitionDTO.model
slide_model = CompetitionDTO.slide_model
team_model = CompetitionDTO.team_model
competition_list_model = CompetitionDTO.user_list_model
def get_comp(CID):
......@@ -69,83 +68,15 @@ class Competitions(Resource):
@api.route("/search")
class CompetitionSearch(Resource):
@jwt_required
@api.marshal_with(competition_model)
@api.marshal_with(competition_list_model)
def get(self):
args = competition_search_parser.parse_args(strict=True)
name = args.get("name")
year = args.get("year")
city_id = args.get("city_id")
style_id = args.get("style_id")
page = args.get("page")
page_size = args.get("page_size")
return dbc.get.search_competitions(name, year, city_id, style_id, page, page_size)
@api.route("/<CID>/slides")
@api.param("CID")
class SlidesList(Resource):
@jwt_required
@api.marshal_with(slide_model)
def get(self, CID):
item_comp = get_comp(CID)
return item_comp.slides
@jwt_required
@api.marshal_with(slide_model)
def post(self, CID):
dbc.add.slide(CID)
item_comp = get_comp(CID)
return item_comp.slides
@api.route("/<CID>/slides/<SID>")
@api.param("CID,SID")
class Slides(Resource):
@jwt_required
@api.marshal_with(slide_model)
def get(self, CID, SID):
item_slide = dbc.get.slide(CID, SID)
return item_slide
@jwt_required
def delete(self, CID, SID):
item_slide = dbc.get.slide(CID, SID)
dbc.delete.slide(item_slide)
return "deleted"
page = args.get("page", 0)
page_size = args.get("page_size", 15)
result, total = dbc.get.search_competitions(name, year, city_id, style_id, page, page_size)
@api.route("/<CID>/teams")
@api.param("CID")
class TeamsList(Resource):
@jwt_required
@api.marshal_with(team_model)
def get(self, CID):
item_comp = get_comp(CID)
return item_comp.teams
@jwt_required
@api.marshal_with(team_model)
def post(self, CID):
parser = reqparse.RequestParser()
parser.add_argument("name", type=str, location="json")
args = competition_parser.parse_args(strict=True)
dbc.add.default(Team(args["name"], CID))
item_comp = get_comp(CID)
return item_comp.teams
@api.route("/<CID>/teams/<TID>")
@api.param("CID,TID")
class Teams(Resource):
@jwt_required
@api.marshal_with(team_model)
def get(self, CID, TID):
item_team = dbc.get.team(CID, TID)
return item_team
@jwt_required
def delete(self, CID, TID):
item_team = dbc.get.team(CID, TID)
dbc.delete.team(item_team)
return "deleted"
return {"competitions": result, "count": len(result), "total": total}
from app.core.dto import MiscDTO
from app.core.models import City, MediaType, QuestionType, Role
from flask_jwt_extended import jwt_required
from flask_restx import Resource
api = MiscDTO.api
question_type_model = MiscDTO.question_type_model
media_type_model = MiscDTO.media_type_model
role_model = MiscDTO.role_model
city_model = MiscDTO.city_model
@api.route("/media_types")
class MediaTypeList(Resource):
@jwt_required
@api.marshal_with(media_type_model)
def get(self):
return MediaType.query.all()
@api.route("/question_types")
class QuestionTypeList(Resource):
@jwt_required
@api.marshal_with(question_type_model)
def get(self):
return QuestionType.query.all()
@api.route("/roles")
class RoleList(Resource):
@jwt_required
@api.marshal_with(role_model)
def get(self):
return Role.query.all()
@api.route("/cities")
class CityList(Resource):
@jwt_required
@api.marshal_with(city_model)
def get(self):
return City.query.all()
import app.core.controller as dbc
import app.core.utils.http_codes as codes
from app.apis import admin_required
from app.core.models import Competition, Slide, User
from app.core.parsers import competition_parser, competition_search_parser
from app.core.schemas import competition_schema
from app.core.dto import SlideDTO
from app.core.models import Competition, Slide
from app.core.parsers import slide_parser
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_restx import Namespace, Resource
from flask_restx import Namespace, Resource, reqparse
api = SlideDTO.api
model = SlideDTO.model
def get_comp(CID):
return Competition.query.filter(Competition.id == CID).first()
@api.route("/")
@api.param("CID")
class SlidesList(Resource):
@jwt_required
@api.marshal_with(model)
def get(self, CID):
item_comp = get_comp(CID)
return item_comp.slides
@jwt_required
@api.marshal_with(model)
def post(self, CID):
dbc.add.slide(CID)
item_comp = get_comp(CID)
return item_comp.slides
@api.route("/<SID>")
@api.param("CID,SID")
class Slides(Resource):
@jwt_required
@api.marshal_with(model)
def get(self, CID, SID):
item_slide = dbc.get.slide(CID, SID)
return item_slide
@jwt_required
@api.marshal_with(model)
def put(self, CID, SID):
args = slide_parser.parse_args(strict=True)
title = args.get("title")
timer = args.get("timer")
item_slide = dbc.get.slide(CID, SID)
return dbc.edit.slide(item_slide, title, timer)
@jwt_required
def delete(self, CID, SID):
item_slide = dbc.get.slide(CID, SID)
dbc.delete.slide(item_slide)
return "deleted"
@api.route("/<SID>/order")
@api.param("CID,SID")
class SlidesOrder(Resource):
@jwt_required
@api.marshal_with(model)
def put(self, CID, SID):
args = slide_parser.parse_args(strict=True)
order = args.get("order")
item_slide = dbc.get.slide(CID, SID)
if order == item_slide.order:
api.abort(codes.BAD_REQUEST)
# clamp order between 0 and max
order_count = Slide.query.filter(Slide.competition_id == item_slide.competition_id).count()
if order < 0:
order = 0
elif order >= order_count - 1:
order = order_count - 1
# get slide at the requested order
item_slide_order = dbc.get.slide_by_order(CID, order)
# switch place between them
item_slide = dbc.edit.switch_order(item_slide, item_slide_order)
return item_slide
import app.core.controller as dbc
import app.core.utils.http_codes as codes
from app.apis import admin_required
from app.core.dto import TeamDTO
from app.core.models import Competition, Team
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_restx import Namespace, Resource, reqparse
api = TeamDTO.api
model = TeamDTO.model
def get_comp(CID):
return Competition.query.filter(Competition.id == CID).first()
@api.route("/")
@api.param("CID")
class TeamsList(Resource):
@jwt_required
@api.marshal_with(model)
def get(self, CID):
item_comp = get_comp(CID)
return item_comp.teams
@jwt_required
@api.marshal_with(model)
def post(self, CID):
parser = reqparse.RequestParser()
parser.add_argument("name", type=str, location="json")
args = parser.parse_args(strict=True)
dbc.add.default(Team(args["name"], CID))
item_comp = get_comp(CID)
return item_comp.teams
@api.route("/<TID>")
@api.param("CID,TID")
class Teams(Resource):
@jwt_required
@api.marshal_with(model)
def get(self, CID, TID):
item_team = dbc.get.team(CID, TID)
return item_team
@jwt_required
def delete(self, CID, TID):
item_team = dbc.get.team(CID, TID)
dbc.delete.team(item_team)
return "deleted"
......@@ -4,12 +4,12 @@ from app.apis import admin_required
from app.core.dto import UserDTO
from app.core.models import User
from app.core.parsers import user_parser, user_search_parser
from app.core.schemas import user_schema
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_restx import Namespace, Resource
api = UserDTO.api
user_model = UserDTO.model
user_list_model = UserDTO.user_list_model
def edit_user(item_user, args):
......@@ -59,14 +59,15 @@ class Users(Resource):
@api.route("/search")
class UserSearch(Resource):
@jwt_required
@api.marshal_list_with(user_model)
@api.marshal_list_with(user_list_model)
def get(self):
args = user_search_parser.parse_args(strict=True)
name = args.get("name")
email = args.get("email")
role_id = args.get("role_id")
city_id = args.get("city_id")
page = args.get("page", 1)
page = args.get("page", 0)
page_size = args.get("page_size", 15)
return dbc.get.search_user(email, name, city_id, role_id, page, page_size)
result, total = dbc.get.search_user(email, name, city_id, role_id, page, page_size)
return {"users": result, "count": len(result), "total": total}
import math
from app.core import db
from app.core.models import Blacklist, City, Competition, Role, Slide, User
def switch_order(item1, item2):
old_order = item1.order
new_order = item2.order
item2.order = -1
db.session.commit()
db.session.refresh(item2)
item1.order = new_order
db.session.commit()
db.session.refresh(item1)
item2.order = old_order
db.session.commit()
db.session.refresh(item2)
return item1
def slide(item, title=None, timer=None):
if title:
item.title = title
if timer:
item.timer = timer
db.session.commit()
db.session.refresh(item)
return item
def competition(item, name=None, year=None, city_id=None, style_id=None):
if name:
item.name = name
......
from app.core.models import Competition, Slide, Team, User
def slide_by_order(CID, order):
return Slide.query.filter((Slide.competition_id == CID) & (Slide.order == order)).first()
def slide(CID, SID):
return Slide.query.filter((Slide.competition_id == CID) & (Slide.id == SID)).first()
......@@ -9,7 +13,7 @@ def team(CID, TID):
return Team.query.filter((Team.competition_id == CID) & (Team.id == TID)).first()
def search_user(email=None, name=None, city_id=None, role_id=None, page=1, page_size=15):
def search_user(email=None, name=None, city_id=None, role_id=None, page=0, page_size=15):
query = User.query
if name:
query = query.filter(User.name.like(f"%{name}%"))
......@@ -20,12 +24,14 @@ def search_user(email=None, name=None, city_id=None, role_id=None, page=1, page_
if role_id:
query = query.filter(User.role_id == role_id)
total = query.count()
query = query.limit(page_size).offset(page * page_size)
result = query.all()
return query.all()
return result, total
def search_competitions(name=None, year=None, city_id=None, style_id=None, page=1, page_size=15):
def search_competitions(name=None, year=None, city_id=None, style_id=None, page=0, page_size=15):
query = Competition.query
if name:
query = query.filter(Competition.name.like(f"%{name}%"))
......@@ -36,6 +42,8 @@ def search_competitions(name=None, year=None, city_id=None, style_id=None, page=
if style_id:
query = query.filter(Competition.style_id == style_id)
total = query.count()
query = query.limit(page_size).offset(page * page_size)
result = query.all()
return query.all()
return result, total
from app.apis import slides
from flask_restx import Namespace, fields
......@@ -19,6 +18,10 @@ class UserDTO:
"city_id": fields.Integer(),
},
)
user_list_model = api.model(
"UserList",
{"users": fields.List(fields.Nested(model)), "count": fields.Integer(), "total": fields.Integer()},
)
class CompetitionDTO:
......@@ -33,15 +36,34 @@ class CompetitionDTO:
"city_id": fields.Integer(),
},
)
slide_model = api.model(
user_list_model = api.model(
"CompetitionList",
{"competitions": fields.List(fields.Nested(model)), "count": fields.Integer(), "total": fields.Integer()},
)
class SlideDTO:
api = Namespace("slides")
model = api.model(
"Slide",
{
"id": fields.Integer(),
"competition_id": fields.Integer(),
"order": fields.Integer(),
"title": fields.String(),
"timer": fields.Integer(),
"competition_id": fields.Integer(),
},
)
team_model = api.model(
"Team", {"id": fields.Integer(), "name": fields.String(), "competition_id": fields.Integer()}
)
class TeamDTO:
api = Namespace("teams")
model = api.model("Team", {"id": fields.Integer(), "name": fields.String(), "competition_id": fields.Integer()})
class MiscDTO:
api = Namespace("misc")
role_model = api.model("Role", {"id": fields.Integer(), "name": fields.String()})
question_type_model = api.model("QuestionType", {"id": fields.Integer(), "name": fields.String()})
media_type_model = api.model("MediaType", {"id": fields.Integer(), "name": fields.String()})
city_model = api.model("City", {"id": fields.Integer(), "name": fields.String()})
......@@ -2,8 +2,8 @@ from flask_restx import inputs, reqparse
###SEARCH####
search_parser = reqparse.RequestParser()
search_parser.add_argument("page", type=int, default=0, location="args")
search_parser.add_argument("page_size", type=int, default=15, location="args")
search_parser.add_argument("page", type=int, default=0)
search_parser.add_argument("page_size", type=int, default=15)
###LOGIN####
login_parser = reqparse.RequestParser()
......@@ -33,15 +33,23 @@ user_search_parser.add_argument("role_id", type=int, default=None, location="arg
###COMPETIION####
competition_parser = reqparse.RequestParser()
competition_parser.add_argument("name", type=str, location="json")
competition_parser.add_argument("year", type=int, location="json")
competition_parser.add_argument("city_id", type=int, location="json")
competition_parser.add_argument("style_id", type=int, location="json")
competition_parser.add_argument("name", type=str)
competition_parser.add_argument("year", type=int)
competition_parser.add_argument("city_id", type=int)
competition_parser.add_argument("style_id", type=int)
###SEARCH_COMPETITOIN####
competition_search_parser = search_parser.copy()
competition_search_parser = reqparse.RequestParser()
# competition_search_parser.add_argument(competition_parser, search_parser)
competition_search_parser.add_argument("name", type=str, default=None, location="args")
competition_search_parser.add_argument("year", type=str, default=None, location="args")
competition_search_parser.add_argument("city_id", type=int, default=None, location="args")
competition_search_parser.add_argument("style_id", type=int, default=None, location="args")
###SEARCH_COMPETITOIN####
slide_parser = reqparse.RequestParser()
slide_parser.add_argument("order", type=int, default=None)
slide_parser.add_argument("title", type=str, default=None)
slide_parser.add_argument("timer", type=int, default=None)
from flask_restx import Namespace, Resource, abort, fields, inputs, model, reqparse
user_schema = (
"User",
{
"id": fields.Integer(),
"name": fields.String(),
"email": fields.String(),
"role_id": fields.Integer(),
"city_id": fields.Integer(),
},
)
competition_schema = (
"Competition",
{
"id": fields.Integer(),
"name": fields.String(),
"year": fields.Integer(),
"style_id": fields.Integer(),
"city_id": fields.Integer(),
},
)
......@@ -31,6 +31,9 @@ def test_competition(client):
assert response.status_code == 200
assert len(body) == 2
response, body = put(client, "/api/competitions/1/slides/1/order", {"order": 1}, headers=headers)
assert response.status_code == 200
response, body = post(client, "/api/competitions/1/teams", {"name": "t1"}, headers=headers)
assert response.status_code == 200
......
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