add pagination, query searching by fullname and ordering by firstname and lastname for list students route
This commit is contained in:
parent
5607f3cd08
commit
40e65c518c
38
backend/app/base/utils.py
Normal file
38
backend/app/base/utils.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from typing import TypedDict, Tuple
|
||||||
|
|
||||||
|
from flask_sqlalchemy import BaseQuery
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
|
|
||||||
|
class PaginationResponse(TypedDict):
|
||||||
|
items: list
|
||||||
|
max_pages: int
|
||||||
|
|
||||||
|
|
||||||
|
def order_by_column_name(query: BaseQuery, model_field: str, order_by_col_name: str) -> BaseQuery:
|
||||||
|
if order_by_col_name is not None:
|
||||||
|
if order_by_col_name == 'asc':
|
||||||
|
query = query.order_by(model_field)
|
||||||
|
elif order_by_col_name == 'desc':
|
||||||
|
query = query.order_by(desc(model_field))
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
def paginate_models(page: str, query: BaseQuery) -> PaginationResponse or Tuple[dict, int]:
|
||||||
|
per_page = 10
|
||||||
|
default_page = 1
|
||||||
|
|
||||||
|
if page is not None:
|
||||||
|
try:
|
||||||
|
page = int(page)
|
||||||
|
except ValueError:
|
||||||
|
return {"error": f"Invalid page! Page must be integer!"}, 400
|
||||||
|
query = query.paginate(page=page, per_page=per_page, error_out=False)
|
||||||
|
else:
|
||||||
|
query = query.paginate(page=default_page, per_page=per_page, error_out=False)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'items': query.items,
|
||||||
|
'max_pages': query.pages
|
||||||
|
}
|
@ -1,14 +1,16 @@
|
|||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
from flask import Blueprint, request, make_response, jsonify, Response
|
from flask import Blueprint, request, Response
|
||||||
from marshmallow import ValidationError
|
from marshmallow import ValidationError
|
||||||
|
from flask_sqlalchemy import get_debug_queries
|
||||||
|
|
||||||
from ...students.models import Student
|
from ...students.models import Student
|
||||||
from ..schemas import StudentSchema, StudentEditSchema, StudentCreateSchema
|
from ..schemas import StudentSchema, StudentEditSchema, StudentCreateSchema
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ..utils import parse_csv
|
from ..utils import parse_csv
|
||||||
from ..exceptions import InvalidNameOrTypeHeaderException
|
from ..exceptions import InvalidNameOrTypeHeaderException
|
||||||
|
from ...base.utils import paginate_models
|
||||||
|
|
||||||
bp = Blueprint("students", __name__, url_prefix="/students")
|
bp = Blueprint("students", __name__, url_prefix="/students")
|
||||||
|
|
||||||
@ -16,8 +18,20 @@ bp = Blueprint("students", __name__, url_prefix="/students")
|
|||||||
@bp.route("/", methods=["GET"])
|
@bp.route("/", methods=["GET"])
|
||||||
def list_students() -> Tuple[dict, int]:
|
def list_students() -> Tuple[dict, int]:
|
||||||
students_schema = StudentSchema(many=True)
|
students_schema = StudentSchema(many=True)
|
||||||
students = Student.query.all()
|
|
||||||
return {"students": students_schema.dump(students)}, 200
|
fullname = request.args.get('fullname')
|
||||||
|
order_by_first_name = request.args.get('order_by_first_name')
|
||||||
|
order_by_last_name = request.args.get('order_by_last_name')
|
||||||
|
page = request.args.get('page')
|
||||||
|
|
||||||
|
student_query = Student.search_by_fullname_and_order_by_first_name_or_last_name(fullname, order_by_first_name,
|
||||||
|
order_by_last_name)
|
||||||
|
|
||||||
|
response = paginate_models(page, student_query)
|
||||||
|
if isinstance(response, tuple):
|
||||||
|
return response
|
||||||
|
print(get_debug_queries()[0])
|
||||||
|
return {"students": students_schema.dump(response['items']), "max_pages": response['max_pages']}, 200
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:index>/", methods=["GET"])
|
@bp.route("/<int:index>/", methods=["GET"])
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
from sqlalchemy.sql import text
|
||||||
|
from flask_sqlalchemy import BaseQuery
|
||||||
|
|
||||||
from ..dependencies import db
|
from ..dependencies import db
|
||||||
from ..base.models import Person, Base
|
from ..base.models import Person, Base
|
||||||
|
from ..base.utils import order_by_column_name
|
||||||
|
|
||||||
|
|
||||||
class ProjectSupervisor(Base, Person):
|
class ProjectSupervisor(Base, Person):
|
||||||
@ -26,3 +30,21 @@ class Student(Person):
|
|||||||
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
|
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
|
||||||
group = db.relationship('Group', backref='students', lazy=True)
|
group = db.relationship('Group', backref='students', lazy=True)
|
||||||
mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary
|
mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def search_by_fullname_and_order_by_first_name_or_last_name(cls, fullname: str = None,
|
||||||
|
order_by_first_name: str = None,
|
||||||
|
order_by_last_name: str = None) -> BaseQuery:
|
||||||
|
student_query = cls.query
|
||||||
|
|
||||||
|
if fullname is not None:
|
||||||
|
"""This works only for sqlite3 database - concat function doesn't exist so i used builtin concat
|
||||||
|
operator specific only for sqlite db - || """
|
||||||
|
student_query = student_query.filter(
|
||||||
|
text("students_first_name || ' ' || students_last_name LIKE :fullname ")
|
||||||
|
).params(fullname=f'{fullname}%')
|
||||||
|
|
||||||
|
student_query = order_by_column_name(student_query, Student.first_name, order_by_first_name)
|
||||||
|
student_query = order_by_column_name(student_query, Student.last_name, order_by_last_name)
|
||||||
|
|
||||||
|
return student_query
|
||||||
|
Loading…
Reference in New Issue
Block a user