如何检查列表中当前用户是否对某些帖子进行了投票

时间:2015-02-20 18:41:36

标签: python django django-models django-views

我是django的新手,所以请耐心等待:)。

和之前的许多人一样,我正在尝试构建一个reddit克隆。我已经完成了所有工作,但缺少一部分。在没有产生太多数据库请求的情况下,我想说明当前用户是否已投票给某个特定问题。

这就是我的模型:

from django.db import models
from django.conf import settings
from mptt.models import MPTTModel, TreeForeignKey

max_post_length = 2000


class Thread(models.Model):
    title = models.CharField(max_length=200)
    text = models.TextField(max_length=max_post_length)
    created = models.DateField()
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    userUpVotes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='threadUpVotes')
    userDownVotes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='threadDownVotes')

    def __str__(self):
        return self.title


class Comment(MPTTModel):
    title = models.CharField(max_length=200)
    text = models.TextField(max_length=max_post_length)
    created = models.DateField()
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    thread = models.ForeignKey(Thread)
    parent = TreeForeignKey('self', related_name='children', blank=True, null=True)
    vote_count = models.IntegerField(default=0)
    userUpVotes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='commentUpVotes')
    userDownVotes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='commentDownVotes')

    class MPTTMeta:
        order_insertion_by = ['created']

    def save(self, *args, **kwargs):
        self.vote_count = self.userUpVotes.count() - self.userDownVotes.count()
        super(Comment, self).save(*args, **kwargs)

    def __str__(self):
        return self.title

这是我的观点:

from django.shortcuts import get_object_or_404, render
from community.models import Thread, Comment
from django.http import HttpResponse


def detail(request, thread_id):
    thread = get_object_or_404(Thread, pk=thread_id)
    comments = thread.comment_set.all()

    return render(request, 'threads/detail.html', {
        'thread': thread,
        'comments': comments
    })

这是我的模板:

{% extends "base.html" %}
{% load mptt_tags %}
{% block content %}
    <h1>{{ thread.title }}</h1>
    <p>{{ thread.text }}</p>
    <ul class="comments">
        {% recursetree comments %}
            <li>
                <div class="comment-block clearfix">
                    <vote-up-down up="{{ node.up_vote_by_user }}"
                                  down="{{ node.user_down_vote }}"
                                  url="/community/comment/{{ node.id }}/vote/"
                                  count="{{ node.vote_count }}"></vote-up-down>
                    <div class="comment">
                        <h4>{{ node.title }}</h4>

                        <div class="text">{{ node.text }}</div>
                    </div>
                </div>
                {% if not node.is_leaf_node %}
                    <ul class="children">
                        {{ children }}
                    </ul>
                {% endif %}
            </li>
        {% endrecursetree %}
    </ul>
{% endblock content %}

填充node.up_vote_by_user和node.down_vote_by_user的最佳方法是什么? 我尝试使用用户中间件和模型方法。我也试过预迭代注释,但这与列表使用的递归不一致。

1 个答案:

答案 0 :(得分:1)

首先,看起来CommentThread的超集,换句话说,它们都使用相同的字段,如titletext,{{1 }},user等,所以如果我在你的位置,我会创建一个名为created的{​​{3}}并将这些字段放入基本模型中:

Node

关于如何查找用户是否投票选择特定问题的实际问题,假设您不想将现有的class Node(models.Model): title = models.CharField(max_length=200) text = models.TextField(max_length=max_post_length) created = models.DateField() user = models.ForeignKey(settings.AUTH_USER_MODEL) up_votes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='%(class)s_upvotes') down_votes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='%(class)s_downvotes') class Meta: abstract = True def __str__(self): return self.title class Thread(Node): pass class Comment(Node, MPTTModel): thread = models.ForeignKey(Thread) parent = TreeForeignKey('self', related_name='children', blank=True, null=True) vote_count = models.IntegerField(default=0) class MPTTMeta(Node.Meta): order_insertion_by = ['created'] 模型替换为现有问题,我肯定会继续使用用户:(我不知道为什么它不适合你)

User

通过这种方式,您甚至不仅可以搜索评论,还可以搜索特定用户投票的线程。但是,为了在模板中使用这些方法,您必须编写自己的abstract base class,将class Node(models.Model): ... def upvoted_by(self, user): return self.up_votes.filter(user=user).exists() def downvoted_by(self, user): return self.down_votes.filter(user=user).exists() 作为参数。

request.user

我不认为您会对上述解决方案的性能感到满意,因为它会针对每个节点实例访问数据库,因此如果线程有太多注释,您最终可能会花费很长时间来加载。因此,更好的选择是迭代用户的向上投票并过滤与线程匹配的那些。

(我认为还有另一种解决方案可以更快,更高效地获取template filter中所有评论对象的后代,但我发现很难理解。)< / p>

@register.filter
def up_voted_by(obj, user):
    return obj.upvoted_by(user)

然后,在您的模板中,您可以轻松检查评论是在def get_all_descendants(nodes, include_self=True): result = set() for node in nodes: descendants = node.get_descendants(include_self=include_self) result.update(set(descendats.values_list('pk', flat=True))) return result def detail(request, thread_id): thread = get_object_or_404(Thread, pk=thread_id) comments = thread.comment_set.all() descendants = get_all_descendants(comments, include_self=True) upvoted_comments = request.user.comment_upvotes.filter( id__in=descendants).values_list('pk', flat=True) downvoted_comments = request.user.comment_downvotes.filter( id__in=descendants).exclude( id__in=upvoted_comments).values_list('pk', flat=True) return render(request, 'threads/detail.html', { 'thread': thread, 'comments': comments, 'upvoted_comments': set(upvoted_comments), 'downvoted_comments': set(downvoted_comments) }) 投票还是投票:

0(1)