djangothreaded-commentsdjango-voting

Django threadedcomments and voting


I'm using django-threadedcomments and django-voting in my project to achieve a Reddit-like comments voting system.

I've set everything up correctly and I'm able to successfully record votes for each threaded comment and its children, however I'm a bit stuck as to how to sort the comments so that the comment with the highest score rises to the top.

Would passing through a template tag be a solution? I've attempted this and returned a list where the items were ordered by score descending, however the parent-child relationship of the comments got messed up. Here is what I did:

class OrderByVotesNode(template.Node):
    def __init__(self, queryset_var, direction="desc"):
        self.queryset_var = template.Variable(queryset_var)
        self.direction = direction

    def render(self, context):
    key = self.queryset_var.var
    value = self.queryset_var.resolve(context)
    try:
        direction = template.Variable(self.direction).resolve(context)
    except template.VariableDoesNotExist:
        direction = "desc"
    model = value.model
    qn = connection.ops.quote_name
    ctype = ContentType.objects.get_for_model(model)
    by_score = model.objects.filter(id__in=[f.id for f in value]).extra(select={"score": """
            SELECT coalesce(SUM(vote), 0 )
            FROM %s
            WHERE content_type_id = %s
            AND object_id = %s.%s
        """ % (qn(Vote._meta.db_table), ctype.id, qn(model._meta.db_table), qn(model._meta.pk.attname))},
        order_by=[(direction == "desc" and "-" or "") + "score"])
    context[key] = by_score
    return u""

Any help or suggestions on this would be greatly appreciated. Thanks!


Solution

  • There are two strategies:

    1) You want to sort only on the topmost comment on every thread. Add a restriction on the query that this comment has no parent comment (I'm not sure how threadedcomments model is designed exactly).

    2) You take the ordered result, and traverse every comment to its root parent. Then, you filter out duplicates from the top to the bottom. This way, each thread is scored according to the maximum score of any comment in the thread. This is harder to implement, and frankly, doesn't seem like the most intuitive order in my mind.

    After you've done this, you have an ordered list of comments that you display in a threaded fashion in the template (I assume you have some template recursion going on).