From b5dd690fbb00808cc2981a1a0a94b940e60fbd95 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Sun, 25 May 2025 17:30:12 -0300 Subject: [PATCH 1/2] feat: with author sorting by shouts, followers and names --- .gitignore | 3 +- resolvers/author.py | 90 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 4db9e7e4..15fc5128 100644 --- a/.gitignore +++ b/.gitignore @@ -161,4 +161,5 @@ views.json *.key *.crt *cache.json -.cursor \ No newline at end of file +.cursor +.devcontainer/devcontainer.json diff --git a/resolvers/author.py b/resolvers/author.py index 91bad2e5..1fa23b70 100644 --- a/resolvers/author.py +++ b/resolvers/author.py @@ -77,18 +77,45 @@ async def get_authors_with_stats(limit=50, offset=0, by: Optional[str] = None): base_query = select(Author).where(Author.deleted_at.is_(None)) # Применяем сортировку + + # vars for statistics sorting + stats_sort_field = None + stats_sort_direction = "desc" + if by: if isinstance(by, dict): + logger.debug(f"Processing dict-based sorting: {by}") # Обработка словаря параметров сортировки - from sqlalchemy import asc, desc + from sqlalchemy import asc, desc, func + from orm.shout import ShoutAuthor + from orm.author import AuthorFollower - for field, direction in by.items(): - column = getattr(Author, field, None) - if column: - if direction.lower() == "desc": + # Checking for order field in the dictionary + if "order" in by: + order_value = by["order"] + logger.debug(f"Found order field with value: {order_value}") + if order_value in ["shouts", "followers", "rating", "comments"]: + stats_sort_field = order_value + stats_sort_direction = "desc" # По умолчанию убывающая сортировка для статистики + logger.debug(f"Applying statistics-based sorting by: {stats_sort_field}") + elif order_value == "name": + # Sorting by name in ascending order + base_query = base_query.order_by(asc(Author.name)) + logger.debug("Applying alphabetical sorting by name") + else: + # If order is not a stats field, treat it as a regular field + column = getattr(Author, order_value, None) + if column: base_query = base_query.order_by(desc(column)) - else: - base_query = base_query.order_by(column) + else: + # Regular sorting by fields + for field, direction in by.items(): + column = getattr(Author, field, None) + if column: + if direction.lower() == "desc": + base_query = base_query.order_by(desc(column)) + else: + base_query = base_query.order_by(column) elif by == "new": base_query = base_query.order_by(desc(Author.created_at)) elif by == "active": @@ -99,6 +126,55 @@ async def get_authors_with_stats(limit=50, offset=0, by: Optional[str] = None): else: base_query = base_query.order_by(desc(Author.created_at)) + # If sorting by statistics, modify the query + if stats_sort_field == "shouts": + # Sorting by the number of shouts + from sqlalchemy import func, and_ + from orm.shout import Shout, ShoutAuthor + + subquery = ( + select( + ShoutAuthor.author, + func.count(func.distinct(Shout.id)).label("shouts_count") + ) + .select_from(ShoutAuthor) + .join(Shout, ShoutAuthor.shout == Shout.id) + .where( + and_( + Shout.deleted_at.is_(None), + Shout.published_at.is_not(None) + ) + ) + .group_by(ShoutAuthor.author) + .subquery() + ) + + base_query = ( + base_query + .outerjoin(subquery, Author.id == subquery.c.author) + .order_by(desc(func.coalesce(subquery.c.shouts_count, 0))) + ) + elif stats_sort_field == "followers": + # Sorting by the number of followers + from sqlalchemy import func + from orm.author import AuthorFollower + + subquery = ( + select( + AuthorFollower.author, + func.count(func.distinct(AuthorFollower.follower)).label("followers_count") + ) + .select_from(AuthorFollower) + .group_by(AuthorFollower.author) + .subquery() + ) + + base_query = ( + base_query + .outerjoin(subquery, Author.id == subquery.c.author) + .order_by(desc(func.coalesce(subquery.c.followers_count, 0))) + ) + # Применяем лимит и смещение base_query = base_query.limit(limit).offset(offset) -- 2.43.0 From 804f900c3868d00cee2d4e9c3c6f593587c20eb1 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Sun, 25 May 2025 20:51:39 +0000 Subject: [PATCH 2/2] style: readme with python granian server start --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68fb1e4f..63b06d44 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ mkcert localhost Then, run the server: ```shell -python server.py dev +python -m granian main:app --interface asgi --host 0.0.0.0 --port 8000 ``` ### Useful Commands -- 2.43.0