model changes

This commit is contained in:
Igor Lobanov
2022-11-29 13:36:46 +01:00
parent b840823fce
commit 226aeddecd
20 changed files with 254 additions and 166 deletions

View File

@@ -1,11 +1,13 @@
from datetime import datetime, timezone
from sqlalchemy import and_
from auth.authenticate import login_required
from base.orm import local_session
from base.resolvers import mutation
from orm.rbac import Resource
from orm.shout import Shout, ShoutAuthor, ShoutTopic
from orm.topic import TopicFollower
from orm.topic import TopicFollower, Topic
from orm.user import User
from resolvers.zine.reactions import reactions_follow, reactions_unfollow
from services.zine.gittask import GitTask
@@ -24,7 +26,7 @@ async def create_shout(_, info, inp):
new_shout = Shout.create(**inp)
# NOTE: shout made by one first author
sa = ShoutAuthor.create(shout=new_shout.slug, user=user.slug)
sa = ShoutAuthor.create(shout_id=new_shout.id, user_id=user.id)
session.add(sa)
reactions_follow(user, new_shout.slug, True)
@@ -33,11 +35,16 @@ async def create_shout(_, info, inp):
topic_slugs.append(inp["mainTopic"])
for slug in topic_slugs:
st = ShoutTopic.create(shout=new_shout.slug, topic=slug)
topic = session.query(Topic).where(Topic.slug == slug).one()
st = ShoutTopic.create(shout_id=new_shout.id, topic_id=topic.id)
session.add(st)
tf = session.query(TopicFollower).where(follower=user.slug, topic=slug)
tf = session.query(TopicFollower).where(
and_(TopicFollower.follower_id == user.id, TopicFollower.topic_id == topic.id)
)
if not tf:
tf = TopicFollower.create(follower=user.slug, topic=slug, auto=True)
tf = TopicFollower.create(follower_id=user.id, topic_id=topic.id, auto=True)
session.add(tf)
new_shout.topic_slugs = topic_slugs
@@ -45,7 +52,7 @@ async def create_shout(_, info, inp):
session.commit()
GitTask(inp, user.username, user.email, "new shout %s" % (new_shout.slug))
GitTask(inp, user.username, user.email, "new shout %s" % new_shout.slug)
return {"shout": new_shout}
@@ -75,7 +82,7 @@ async def update_shout(_, info, inp):
session.add(shout)
if inp.get("topics"):
# remove old links
links = session.query(ShoutTopic).where(ShoutTopic.shout == slug).all()
links = session.query(ShoutTopic).where(ShoutTopic.shout_id == shout.id).all()
for topiclink in links:
session.delete(topiclink)
# add new topic links

View File

@@ -4,7 +4,7 @@ from auth.authenticate import login_required
from base.redis import redis
from base.resolvers import query
from base.orm import local_session
from orm.user import AuthorFollower
from orm.user import AuthorFollower, User
@query.field("searchRecipients")
@@ -30,13 +30,19 @@ async def search_recipients(_, info, query: str, limit: int = 50, offset: int =
with local_session() as session:
# followings
result += session.query(AuthorFollower.author).where(AuthorFollower.follower.startswith(query))\
.offset(offset + len(result)).limit(more_amount)
result += session.query(AuthorFollower.author).join(
User, User.id == AuthorFollower.follower_id
).where(
User.slug.startswith(query)
).offset(offset + len(result)).limit(more_amount)
more_amount = limit
# followers
result += session.query(AuthorFollower.follower).where(AuthorFollower.author.startswith(query))\
.offset(offset + len(result)).limit(offset + len(result) + limit)
result += session.query(AuthorFollower.follower).join(
User, User.id == AuthorFollower.author_id
).where(
User.slug.startswith(query)
).offset(offset + len(result)).limit(offset + len(result) + limit)
return {
"members": list(result),
"error": None

View File

@@ -1,11 +1,11 @@
from datetime import datetime, timedelta, timezone
from sqlalchemy.orm import joinedload, aliased
from sqlalchemy.sql.expression import desc, asc, select, case, func
from sqlalchemy.sql.expression import desc, asc, select, func
from base.orm import local_session
from base.resolvers import query
from orm import ViewedEntry
from orm.shout import Shout, ShoutAuthor
from orm.reaction import Reaction, ReactionKind
from orm.reaction import Reaction
from resolvers.zine._common import add_common_stat_columns
@@ -18,7 +18,7 @@ def add_stat_columns(q):
def apply_filters(q, filters, user=None):
if filters.get("reacted") and user:
q.join(Reaction, Reaction.createdBy == user.slug)
q.join(Reaction, Reaction.createdBy == user.id)
v = filters.get("visibility")
if v == "public":
@@ -66,9 +66,9 @@ async def load_shout(_, info, slug):
"rating": rating_stat
}
for author_caption in session.query(ShoutAuthor).where(ShoutAuthor.shout == slug):
for author_caption in session.query(ShoutAuthor).join(Shout).where(Shout.slug == slug):
for author in shout.authors:
if author.slug == author_caption.user:
if author.id == author_caption.user_id:
author.caption = author_caption.caption
return shout

View File

@@ -19,17 +19,19 @@ from resolvers.zine.topics import followed_by_user
def add_author_stat_columns(q):
author_followers = aliased(AuthorFollower)
author_following = aliased(AuthorFollower)
shout_author_aliased = aliased(ShoutAuthor)
user_rating_aliased = aliased(UserRating)
q = q.outerjoin(ShoutAuthor).add_columns(
func.count(distinct(ShoutAuthor.shout)).label('shouts_stat')
).outerjoin(author_followers, author_followers.author == User.slug).add_columns(
func.count(distinct(author_followers.follower)).label('followers_stat')
).outerjoin(author_following, author_following.follower == User.slug).add_columns(
func.count(distinct(author_following.author)).label('followings_stat')
).outerjoin(UserRating).add_columns(
q = q.outerjoin(shout_author_aliased).add_columns(
func.count(distinct(shout_author_aliased.shout_id)).label('shouts_stat')
).outerjoin(author_followers, author_followers.author_id == User.id).add_columns(
func.count(distinct(author_followers.follower_id)).label('followers_stat')
).outerjoin(author_following, author_following.follower_id == User.id).add_columns(
func.count(distinct(author_following.author_id)).label('followings_stat')
).outerjoin(user_rating_aliased, user_rating_aliased.user_id == User.id).add_columns(
# TODO: check
func.sum(UserRating.value).label('rating_stat')
).outerjoin(Reaction, and_(Reaction.createdBy == User.slug, Reaction.body.is_not(None))).add_columns(
func.sum(user_rating_aliased.value).label('rating_stat')
).outerjoin(Reaction, and_(Reaction.createdBy == User.id, Reaction.body.is_not(None))).add_columns(
func.count(distinct(Reaction.id)).label('commented_stat')
)
@@ -83,7 +85,7 @@ async def followed_reactions(slug):
return session.query(
Reaction.shout
).where(
Reaction.createdBy == slug
Reaction.createdBy == user.id
).filter(
Reaction.createdAt > user.lastSeen
).all()
@@ -107,7 +109,7 @@ async def get_followed_authors(_, _info, slug) -> List[User]:
async def followed_authors(slug) -> List[User]:
q = select(User)
q = add_author_stat_columns(q)
q = q.join(AuthorFollower).where(AuthorFollower.follower == slug)
q = q.join(AuthorFollower).join(User, User.id == AuthorFollower.follower_id).where(User.slug == slug)
return get_authors_from_query(q)
@@ -116,7 +118,13 @@ async def followed_authors(slug) -> List[User]:
async def user_followers(_, _info, slug) -> List[User]:
q = select(User)
q = add_author_stat_columns(q)
q = q.join(AuthorFollower).where(AuthorFollower.author == slug)
aliased_user = aliased(User)
q = q.join(AuthorFollower).join(
aliased_user, aliased_user.id == AuthorFollower.author_id
).where(
aliased_user.slug == slug
)
return get_authors_from_query(q)
@@ -173,7 +181,8 @@ async def rate_user(_, info, rated_userslug, value):
# for mutation.field("follow")
def author_follow(user, slug):
with local_session() as session:
af = AuthorFollower.create(follower=user.slug, author=slug)
author = session.query(User).where(User.slug == slug).one()
af = AuthorFollower.create(follower_id=user.id, author_id=author.id)
session.add(af)
session.commit()
@@ -182,13 +191,13 @@ def author_follow(user, slug):
def author_unfollow(user, slug):
with local_session() as session:
flw = (
session.query(AuthorFollower)
.filter(
session.query(
AuthorFollower
).join(User, User.id == AuthorFollower.author_id).filter(
and_(
AuthorFollower.follower == user.slug, AuthorFollower.author == slug
AuthorFollower.follower_id == user.id, User.slug == slug
)
)
.first()
).first()
)
if not flw:
raise Exception("[resolvers.profile] follower not exist, cant unfollow")
@@ -224,7 +233,7 @@ async def load_authors_by(_, info, by, limit, offset):
elif by.get("name"):
q = q.filter(User.name.ilike(f"%{by['name']}%"))
elif by.get("topic"):
q = q.join(ShoutAuthor).join(ShoutTopic).where(ShoutTopic.topic == by["topic"])
q = q.join(ShoutAuthor).join(ShoutTopic).join(Topic).where(Topic.slug == by["topic"])
if by.get("lastSeen"): # in days
days_before = datetime.now(tz=timezone.utc) - timedelta(days=by["lastSeen"])
q = q.filter(User.lastSeen > days_before)

View File

@@ -16,16 +16,19 @@ def add_reaction_stat_columns(q):
def reactions_follow(user: User, slug: str, auto=False):
with local_session() as session:
shout = session.query(Shout).where(Shout.slug == slug).one()
following = (
session.query(ShoutReactionsFollower).where(and_(
ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug
ShoutReactionsFollower.follower_id == user.id,
ShoutReactionsFollower.shout_id == shout.id,
)).first()
)
if not following:
following = ShoutReactionsFollower.create(
follower=user.slug,
shout=slug,
follower_id=user.id,
shout_id=shout.id,
auto=auto
)
session.add(following)
@@ -34,12 +37,15 @@ def reactions_follow(user: User, slug: str, auto=False):
def reactions_unfollow(user, slug):
with local_session() as session:
shout = session.query(Shout).where(Shout.slug == slug).one()
following = (
session.query(ShoutReactionsFollower).where(and_(
ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug
ShoutReactionsFollower.follower_id == user.id,
ShoutReactionsFollower.shout_id == shout.id
)).first()
)
if following:
session.delete(following)
session.commit()
@@ -68,7 +74,7 @@ def check_to_publish(session, user, reaction):
]:
if is_published_author(user):
# now count how many approvers are voted already
approvers_reactions = session.query(Reaction).where(Reaction.shout == reaction.shout).all()
approvers_reactions = session.query(Reaction).where(Reaction.shout_id == reaction.shout_id).all()
approvers = [user.slug, ]
for ar in approvers_reactions:
a = ar.createdBy
@@ -87,7 +93,7 @@ def check_to_hide(session, user, reaction):
ReactionKind.UNPROOF
]:
# if is_published_author(user):
approvers_reactions = session.query(Reaction).where(Reaction.shout == reaction.shout).all()
approvers_reactions = session.query(Reaction).where(Reaction.shout_id == reaction.shout_id).all()
declines = 0
for r in approvers_reactions:
if r.kind in [
@@ -224,22 +230,26 @@ async def load_reactions_by(_, _info, by, limit=50, offset=0):
q = select(
Reaction, CreatedByUser, ReactedShout
).join(
CreatedByUser, Reaction.createdBy == CreatedByUser.slug
CreatedByUser, Reaction.createdBy == CreatedByUser.id
).join(
ReactedShout, Reaction.shout == ReactedShout.slug
ReactedShout, Reaction.shout_id == ReactedShout.id
)
if by.get("shout"):
q = q.filter(Reaction.shout == by["shout"])
aliased_shout = aliased(Shout)
q = q.join(aliased_shout).filter(aliased_shout.slug == by["shout"])
elif by.get("shouts"):
q = q.filter(Reaction.shout.in_(by["shouts"]))
aliased_shout = aliased(Shout)
q = q.join(aliased_shout).filter(aliased_shout.shout.in_(by["shouts"]))
if by.get("createdBy"):
q = q.filter(Reaction.createdBy == by.get("createdBy"))
aliased_user = aliased(User)
q = q.join(aliased_user).filter(aliased_user.slug == by.get("createdBy"))
if by.get("topic"):
# TODO: check
q = q.filter(Shout.topics.contains(by["topic"]))
if by.get("comment"):
q = q.filter(func.length(Reaction.body) > 0)
if by.get('search', 0) > 2:
if len(by.get('search', '')) > 2:
q = q.filter(Reaction.body.ilike(f'%{by["body"]}%'))
if by.get("days"):
after = datetime.now(tz=timezone.utc) - timedelta(days=int(by["days"]) or 30)

View File

@@ -4,20 +4,20 @@ from base.orm import local_session
from base.resolvers import mutation, query
from orm.shout import ShoutTopic, ShoutAuthor
from orm.topic import Topic, TopicFollower
from orm import Shout
from orm import Shout, User
def add_topic_stat_columns(q):
q = q.outerjoin(ShoutTopic, Topic.slug == ShoutTopic.topic).add_columns(
func.count(distinct(ShoutTopic.shout)).label('shouts_stat')
).outerjoin(ShoutAuthor, ShoutTopic.shout == ShoutAuthor.shout).add_columns(
func.count(distinct(ShoutAuthor.user)).label('authors_stat')
q = q.outerjoin(ShoutTopic, Topic.id == ShoutTopic.topic_id).add_columns(
func.count(distinct(ShoutTopic.shout_id)).label('shouts_stat')
).outerjoin(ShoutAuthor, ShoutTopic.shout_id == ShoutAuthor.shout_id).add_columns(
func.count(distinct(ShoutAuthor.user_id)).label('authors_stat')
).outerjoin(TopicFollower,
and_(
TopicFollower.topic == Topic.slug,
TopicFollower.follower == ShoutAuthor.user
TopicFollower.topic_id == Topic.id,
TopicFollower.follower_id == ShoutAuthor.id
)).add_columns(
func.count(distinct(TopicFollower.follower)).label('followers_stat')
func.count(distinct(TopicFollower.follower_id)).label('followers_stat')
)
q = q.group_by(Topic.id)
@@ -49,7 +49,7 @@ def get_topics_from_query(q):
def followed_by_user(user_slug):
q = select(Topic)
q = add_topic_stat_columns(q)
q = q.where(TopicFollower.follower == user_slug)
q = q.join(User).where(User.slug == user_slug)
return get_topics_from_query(q)
@@ -74,7 +74,7 @@ async def topics_by_community(_, info, community):
async def topics_by_author(_, _info, author):
q = select(Topic)
q = add_topic_stat_columns(q)
q = q.where(ShoutAuthor.user == author)
q = q.join(User).where(User.slug == author)
return get_topics_from_query(q)
@@ -117,7 +117,9 @@ async def update_topic(_, _info, inp):
async def topic_follow(user, slug):
with local_session() as session:
following = TopicFollower.create(topic=slug, follower=user.slug)
topic = session.query(Topic).where(Topic.slug == slug).one()
following = TopicFollower.create(topic_id=topic.id, follower=user.id)
session.add(following)
session.commit()
@@ -125,10 +127,10 @@ async def topic_follow(user, slug):
async def topic_unfollow(user, slug):
with local_session() as session:
sub = (
session.query(TopicFollower).filter(
session.query(TopicFollower).join(Topic).filter(
and_(
TopicFollower.follower == user.slug,
TopicFollower.topic == slug
TopicFollower.follower_id == user.id,
Topic.slug == slug
)
).first()
)
@@ -143,7 +145,7 @@ async def topic_unfollow(user, slug):
async def topics_random(_, info, amount=12):
q = select(Topic)
q = add_topic_stat_columns(q)
q = q.join(Shout, ShoutTopic.shout == Shout.slug).group_by(Topic.id).having(func.count(Shout.id) > 2)
q = q.join(Shout, ShoutTopic.shout_id == Shout.id).group_by(Topic.id).having(func.count(Shout.id) > 2)
q = q.order_by(func.random()).limit(amount)
return get_topics_from_query(q)