Alessandro Molina avatar Alessandro Molina committed 81e2926

Some support tools for comments votes

Comments (0)

Files changed (4)

-    version='0.0.3',
+    version='0.0.4',
     description='TurboGears2 pluggable application for comments to entities with facebook sharing',
     author='Alessandro Molina',


 from tg.i18n import ugettext as _, lazy_ugettext as l_
 from tgcomments import model
-from tgcomments.model import DBSession, Comment
+from tgcomments.model import DBSession, Comment, CommentVote
 from tgcomments.lib import get_user_gravatar, notify_comment_on_facebook, make_fake_comment_entity, FakeCommentEntity
 from tgext.pluggable import app_model
-from formencode.validators import Email, String, Invalid
+from formencode.validators import Email, String, Invalid, Int
 from tgext.datahelpers.validators import SQLAEntityConverter
 from tgext.datahelpers.utils import fail_with
             flash(_('Comment Displayed'))
         return back_to_referer(success=True)
+    @expose()
+    @require(predicates.not_anonymous())
+    @validate({'comment':SQLAEntityConverter(Comment),
+               'value':Int(not_empty=True)},
+              error_handler=fail_with(403))
+    def vote(self, comment, value):
+        user = request.identity['user']
+        vote = DBSession.query(CommentVote).filter_by(comment=comment).filter_by(user=user).first()
+        if not vote:
+            vote = CommentVote(comment=comment, user=user)
+            DBSession.add(vote)
+        votes_range = config['_pluggable_tgcomments_config'].get('votes_range', (-1, 1))
+        min_vote_value = votes_range[0]
+        max_vote_value = votes_range[1]
+        vote.value = min(max(min_vote_value, value), max_vote_value)
+        flash(_('Thanks for your vote!'))
+        return back_to_referer(success=True)


 def init_model(app_session):
-from models import Comment
+from models import Comment, CommentVote


 import tg
 from sqlalchemy import Table, ForeignKey, Column
-from sqlalchemy.types import Unicode, Integer, DateTime, UnicodeText, Boolean
+from sqlalchemy.types import Unicode, Integer, DateTime, UnicodeText, Boolean, String
 from sqlalchemy.orm import backref, relation
 from tgcomments.model import DeclarativeBase, DBSession
     entity_id = Column(Integer, nullable=False, index=True)
     entity_type = Column(Unicode(255), nullable=False, index=True)
+    @property
+    def voters(self):
+        return DBSession.query(app_model.User).join(CommentVote).filter(CommentVote.comment_id==self.uid)
+    @property
+    def rank(self):
+        sum((v.value for v in self.votes))
+    def votes_by_value(self, v):
+        return DBSession.query(CommentVote).filter_by(comment_id=self.uid).filter_by(value=v)
     def get_entity_descriptor(cls, entity):
         Type = entity.__class__
         return c
+class CommentVote(DeclarativeBase):
+    __tablename__ = 'tgcomments_comments_votes'
+    __table_args__ = (Index('idx_comment_voter', "comment_id", "user_id", unique=True), )
+    uid = Column(Integer, autoincrement=True, primary_key=True)
+    created_at = Column(DateTime,, nullable=False)
+    value = Column(Integer, default=1)
+    user_id = Column(Integer, ForeignKey(primary_key(app_model.User)), nullable=False)
+    user = relation(app_model.User, backref=backref('comments_votes'))
+    comment_id = Column(Integer, ForeignKey(Comment.uid), nullable=False)
+    comment = relation(Comment, backref=backref('votes'))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.