From 64e807a0b5ca0dd1601d548e79780189e12bcb91 Mon Sep 17 00:00:00 2001 From: Timur Enikeev Date: Mon, 18 Nov 2024 04:10:31 -0500 Subject: [PATCH] Add sort_order option --- rating_api/models/db.py | 15 ++++++++++++++- rating_api/routes/lecturer.py | 11 ++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/rating_api/models/db.py b/rating_api/models/db.py index 6564765..1c0e1b8 100644 --- a/rating_api/models/db.py +++ b/rating_api/models/db.py @@ -7,9 +7,10 @@ from sqlalchemy import UUID, Boolean, DateTime from sqlalchemy import Enum as DbEnum -from sqlalchemy import ForeignKey, Integer, String, and_, func, or_, true +from sqlalchemy import ForeignKey, Integer, String, UnaryExpression, and_, func, nulls_last, or_, true from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm.attributes import InstrumentedAttribute from rating_api.settings import get_settings @@ -60,6 +61,18 @@ def search_by_subject(self, query: str) -> bool: response = and_(Comment.review_status == ReviewStatus.APPROVED, func.lower(Comment.subject).contains(query)) return response + @hybrid_method + def order_by_mark(self, query: str, asc_order: bool) -> UnaryExpression[float]: + return ( + nulls_last(func.avg(getattr(Comment, query))) + if asc_order + else nulls_last(func.avg(getattr(Comment, query)).desc()) + ) + + @hybrid_method + def order_by_name(self, query: str, asc_order: bool) -> UnaryExpression[str] | InstrumentedAttribute[str]: + return getattr(Lecturer, query) if asc_order else getattr(Lecturer, query).desc() + class Comment(BaseDbModel): uuid: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) diff --git a/rating_api/routes/lecturer.py b/rating_api/routes/lecturer.py index 55512b5..1bdd563 100644 --- a/rating_api/routes/lecturer.py +++ b/rating_api/routes/lecturer.py @@ -3,7 +3,7 @@ from auth_lib.fastapi import UnionAuth from fastapi import APIRouter, Depends, Query from fastapi_sqlalchemy import db -from sqlalchemy import and_, func, nulls_last +from sqlalchemy import and_ from rating_api.exceptions import AlreadyExists, ObjectNotFound from rating_api.models import Comment, Lecturer, LecturerUserComment, ReviewStatus @@ -80,6 +80,7 @@ async def get_lecturers( ), subject: str = Query(''), name: str = Query(''), + asc_order: bool = False, ) -> LecturerGetAll: """ `limit` - максимальное количество возвращаемых преподавателей @@ -100,6 +101,10 @@ async def get_lecturers( `name` Поле для ФИО. Если передано `name` - возвращает всех преподователей, для которых нашлись совпадения с переданной строкой + + `asc_order` + Если передано true, сортировать в порядке возрастания + Иначе - в порядке убывания """ lecturers_query = ( Lecturer.query(session=db.session) @@ -108,9 +113,9 @@ async def get_lecturers( .filter(Lecturer.search_by_subject(subject)) .filter(Lecturer.search_by_name(name)) .order_by( - nulls_last(func.avg(getattr(Comment, order_by)).desc()) + Lecturer.order_by_mark(order_by, asc_order) if "mark" in order_by - else getattr(Lecturer, order_by) + else Lecturer.order_by_name(order_by, asc_order) ) )