From 9a5ec80b123c8e99f681b5a25843b57afc7ffd07 Mon Sep 17 00:00:00 2001 From: knst-kotov Date: Fri, 24 Sep 2021 17:39:37 +0300 Subject: [PATCH] get Shout with additional info --- orm/__init__.py | 9 +++++++-- orm/shout.py | 35 +++++++++++++++++++++++++++++++++-- resolvers/zine.py | 23 +++++++++++------------ 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/orm/__init__.py b/orm/__init__.py index ac60adde..bd267234 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -4,8 +4,9 @@ from orm.user import User from orm.message import Message from orm.topic import Topic from orm.notification import Notification -from orm.shout import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay -from orm.base import Base, engine +from orm.shout import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay,\ + ShoutRatingStorage, ShoutViewStorage +from orm.base import Base, engine, local_session from orm.comment import Comment __all__ = ["User", "Role", "Operation", "Permission", "Message", "Shout", "Topic", "Notification"] @@ -13,3 +14,7 @@ __all__ = ["User", "Role", "Operation", "Permission", "Message", "Shout", "Topic Base.metadata.create_all(engine) Operation.init_table() Resource.init_table() + +with local_session() as session: + rating_storage = ShoutRatingStorage(session) + view_storage = ShoutViewStorage(session) diff --git a/orm/shout.py b/orm/shout.py index e3b73dfe..afe5d4d5 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -6,6 +6,8 @@ from orm import Permission, User, Topic from orm.comment import Comment from orm.base import Base +from functools import reduce + class ShoutAuthor(Base): __tablename__ = "shout_author" @@ -36,6 +38,25 @@ class ShoutRating(Base): ts: str = Column(DateTime, nullable=False, default = datetime.now, comment="Timestamp") value = Column(Integer) +class ShoutRatingStorage: + + def __init__(self, session): + self.ratings = session.query(ShoutRating).all() + + def get_rating(self, shout_id): + shout_ratings = list(filter(lambda x: x.shout_id == shout_id, self.ratings)) + return reduce((lambda x, y: x + y.value), shout_ratings, 0) + + def update_rating(self, new_rating): + rating = next(x for x in self.ratings \ + if x.rater_id == new_rating.rater_id and x.shout_id == new_rating.shout_id) + if rating: + rating.value = new_rating.value + rating.ts = new_rating.ts + else: + self.ratings.append(new_rating) + + class ShoutViewByDay(Base): __tablename__ = "shout_view_by_day" @@ -44,6 +65,18 @@ class ShoutViewByDay(Base): day: str = Column(DateTime, primary_key = True, default = datetime.now) value = Column(Integer) +class ShoutViewStorage: + + def __init__(self, session): + self.views = session.query(ShoutViewByDay).all() + + def get_view(self, shout_id): + shout_views = list(filter(lambda x: x.shout_id == shout_id, self.views)) + return reduce((lambda x, y: x + y.value), shout_views, 0) + + def add_view(self, view): + self.views.append(view) + class Shout(Base): __tablename__ = 'shout' @@ -66,7 +99,5 @@ class Shout(Base): layout: str = Column(String, nullable = True) authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__) # NOTE: multiple authors topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) - ratings = relationship(ShoutRating, foreign_keys=ShoutRating.shout_id) - views = relationship(ShoutViewByDay) visibleFor = relationship(lambda: User, secondary=ShoutViewer.__tablename__) old_id: str = Column(String, nullable = True) diff --git a/resolvers/zine.py b/resolvers/zine.py index b13cfe50..e0c12ef3 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -1,4 +1,5 @@ -from orm import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay, User, Community, Resource +from orm import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay, User, Community, Resource,\ + rating_storage, view_storage from orm.base import local_session from resolvers.base import mutation, query @@ -12,6 +13,7 @@ from datetime import datetime, timedelta from pathlib import Path from sqlalchemy import select, func, desc +from sqlalchemy.orm import selectinload class GitTask: @@ -258,17 +260,14 @@ async def update_shout(_, info, id, input): "shout" : shout } -@query.field("getShoutBySlug") #FIXME: add shout joined with comments +@query.field("getShoutBySlug") async def get_shout_by_slug(_, info, slug): with local_session() as session: - stmt = select(Shout, func.sum(ShoutRating.value).label("rating")).\ - join(ShoutRating).\ - where(Shout.slug == slug).\ - limit(limit) - shouts = [] - for row in session.execute(stmt): - shout = row.Shout - shout.rating = row.rating - # TODO: shout.comments = - shouts.append(shout) + shout = session.query(Shout).\ + options(selectinload(Shout.authors)).\ + options(selectinload(Shout.comments)).\ + options(selectinload(Shout.topics)).\ + filter(Shout.slug == slug).first() + shout.rating = rating_storage.get_rating(shout.id) + shout.views = view_storage.get_view(shout.id) return shout