Browse Source

Add weights to comment tags

This gives each comment tag a "weight" value, which is a float. This
weight can be set for each user to affect their future comment tags, and
if a user doesn't have a weight set it uses a global default value
that's set in the INI file. This global default is set to 1.0 for
development purposes, since that should make it so that a single tag
will have an effect. It should probably be set lower initially in
production so that single users can't cause tag effects.
merge-requests/37/head
Deimos 6 years ago
parent
commit
89cf27562f
  1. 29
      tildes/alembic/versions/b825165870d9_add_weights_to_comment_tags.py
  2. 2
      tildes/development.ini
  3. 1
      tildes/production.ini.example
  4. 9
      tildes/tildes/models/comment/comment.py
  5. 8
      tildes/tildes/models/comment/comment_tag.py
  6. 2
      tildes/tildes/models/user/user.py
  7. 6
      tildes/tildes/templates/macros/comments.jinja2
  8. 6
      tildes/tildes/views/api/web/comment.py

29
tildes/alembic/versions/b825165870d9_add_weights_to_comment_tags.py

@ -0,0 +1,29 @@
"""Add weights to comment tags
Revision ID: b825165870d9
Revises: 6ede05a0ea23
Create Date: 2018-09-14 03:06:51.144073
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "b825165870d9"
down_revision = "6ede05a0ea23"
branch_labels = None
depends_on = None
def upgrade():
op.add_column(
"comment_tags",
sa.Column("weight", sa.REAL(), server_default=sa.text("1.0"), nullable=False),
)
op.add_column("users", sa.Column("comment_tag_weight", sa.REAL(), nullable=True))
def downgrade():
op.drop_column("users", "comment_tag_weight")
op.drop_column("comment_tags", "weight")

2
tildes/development.ini

@ -36,6 +36,8 @@ redis.sessions.timeout = 600
sqlalchemy.url = postgresql+psycopg2://tildes:@:6432/tildes sqlalchemy.url = postgresql+psycopg2://tildes:@:6432/tildes
tildes.default_user_comment_tag_weight = 1.0
webassets.auto_build = false webassets.auto_build = false
webassets.base_dir = %(here)s/static webassets.base_dir = %(here)s/static
webassets.base_url = / webassets.base_url = /

1
tildes/production.ini.example

@ -20,6 +20,7 @@ redis.sessions.timeout = 3600
sqlalchemy.url = postgresql+psycopg2://tildes:@:6432/tildes sqlalchemy.url = postgresql+psycopg2://tildes:@:6432/tildes
tildes.default_user_comment_tag_weight = 1.0
tildes.welcome_message_sender = Deimos tildes.welcome_message_sender = Deimos
webassets.auto_build = false webassets.auto_build = false

9
tildes/tildes/models/comment/comment.py

@ -238,6 +238,15 @@ class Comment(DatabaseModel):
"""Counter for number of times each tag is on this comment.""" """Counter for number of times each tag is on this comment."""
return Counter([tag.name for tag in self.tags]) return Counter([tag.name for tag in self.tags])
@property
def tag_weights(self) -> Counter:
"""Counter with cumulative weights of each tag on this comment."""
weights: Counter = Counter()
for tag in self.tags:
weights[tag.name] += tag.weight
return weights
def tags_by_user(self, user: User) -> Sequence[str]: def tags_by_user(self, user: User) -> Sequence[str]:
"""Return list of tag names that a user has applied to this comment.""" """Return list of tag names that a user has applied to this comment."""
return [tag.name for tag in self.tags if tag.user_id == user.user_id] return [tag.name for tag in self.tags if tag.user_id == user.user_id]

8
tildes/tildes/models/comment/comment_tag.py

@ -5,7 +5,7 @@
from datetime import datetime from datetime import datetime
from sqlalchemy import Column, ForeignKey, Integer, TIMESTAMP
from sqlalchemy import Column, ForeignKey, Integer, REAL, TIMESTAMP
from sqlalchemy.dialects.postgresql import ENUM from sqlalchemy.dialects.postgresql import ENUM
from sqlalchemy.orm import backref, relationship from sqlalchemy.orm import backref, relationship
from sqlalchemy.sql.expression import text from sqlalchemy.sql.expression import text
@ -33,15 +33,19 @@ class CommentTag(DatabaseModel):
created_time: datetime = Column( created_time: datetime = Column(
TIMESTAMP(timezone=True), nullable=False, server_default=text("NOW()") TIMESTAMP(timezone=True), nullable=False, server_default=text("NOW()")
) )
weight: float = Column(REAL, nullable=False, server_default=text("1.0"))
comment: Comment = relationship(Comment, backref=backref("tags", lazy=False)) comment: Comment = relationship(Comment, backref=backref("tags", lazy=False))
user: User = relationship(User, lazy=False, innerjoin=True) user: User = relationship(User, lazy=False, innerjoin=True)
def __init__(self, comment: Comment, user: User, tag: CommentTagOption) -> None:
def __init__(
self, comment: Comment, user: User, tag: CommentTagOption, weight: float
) -> None:
"""Add a new tag to a comment.""" """Add a new tag to a comment."""
self.comment_id = comment.comment_id self.comment_id = comment.comment_id
self.user_id = user.user_id self.user_id = user.user_id
self.tag = tag self.tag = tag
self.weight = weight
@property @property
def name(self) -> str: def name(self) -> str:

2
tildes/tildes/models/user/user.py

@ -22,6 +22,7 @@ from sqlalchemy import (
Column, Column,
ForeignKey, ForeignKey,
Integer, Integer,
REAL,
Text, Text,
TIMESTAMP, TIMESTAMP,
) )
@ -100,6 +101,7 @@ class User(DatabaseModel):
_filtered_topic_tags: List[Ltree] = Column( _filtered_topic_tags: List[Ltree] = Column(
"filtered_topic_tags", ArrayOfLtree, nullable=False, server_default="{}" "filtered_topic_tags", ArrayOfLtree, nullable=False, server_default="{}"
) )
comment_tag_weight: Optional[float] = Column(REAL)
@hybrid_property @hybrid_property
def filtered_topic_tags(self) -> List[str]: def filtered_topic_tags(self) -> List[str]:

6
tildes/tildes/templates/macros/comments.jinja2

@ -98,13 +98,13 @@
{% if comment.tag_counts and request.has_permission("view_tags", comment) %} {% if comment.tag_counts and request.has_permission("view_tags", comment) %}
<ul class="comment-tags"> <ul class="comment-tags">
{% for tag_name, count in comment.tag_counts.most_common() %}
{% for tag_name, weight in comment.tag_weights.most_common() %}
<li> <li>
<span class="label label-comment-tag label-comment-tag-{{ tag_name|lower }}">{{ tag_name }}</span> <span class="label label-comment-tag label-comment-tag-{{ tag_name|lower }}">{{ tag_name }}</span>
<span class="comment-tag-count"> <span class="comment-tag-count">
x{{ count }}:
{{ weight }}:
{% for tag in comment.tags if tag.name == tag_name %} {% for tag in comment.tags if tag.name == tag_name %}
{{ username_linked(tag.user.username) }}
{{ username_linked(tag.user.username) }} ({{ tag.weight }})
{% endfor %} {% endfor %}
</span> </span>
</li> </li>

6
tildes/tildes/views/api/web/comment.py

@ -259,7 +259,11 @@ def put_tag_comment(request: Request, name: CommentTagOption) -> Response:
savepoint = request.tm.savepoint() savepoint = request.tm.savepoint()
tag = CommentTag(comment, request.user, name)
weight = request.user.comment_tag_weight
if weight is None:
weight = request.registry.settings["tildes.default_user_comment_tag_weight"]
tag = CommentTag(comment, request.user, name, weight)
request.db_session.add(tag) request.db_session.add(tag)
try: try:

Loading…
Cancel
Save