You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django中不修改第三方django-contrib-comments架构,如何关联评论用户的Poller投票记录?

解决方案:无需修改第三方库,通过关联查询获取用户投票记录

完全理解你的需求——不想碰django-contrib-comments的代码,只想在自己的视图和模板里搞定评论与对应投票的展示。其实不用子类化CommentAbstractModel,咱们通过关联查询预取就能完美解决这个问题,具体步骤如下:

第一步:给Vote模型加唯一性约束(可选但强烈推荐)

首先,为了确保一个用户对同一个Poller只能投一次票,先在Vote模型的Meta类里加个联合唯一约束,避免后续出现一个用户多条投票记录的混乱:

class Vote(models.Model):
    poller = models.ForeignKey(Poller, on_delete=models.CASCADE, related_name='vote')
    user = models.ForeignKey(Account, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)
    poller_choice_one_vote = models.BooleanField(default=False)
    poller_choice_two_vote = models.BooleanField(default=False)
    
    class Meta:
        # 确保一个用户对一个Poller只能有一条投票记录
        unique_together = ('poller', 'user')

第二步:在single_poller视图中预取评论与对应投票

接下来修改你的视图,获取当前Poller的所有评论,同时通过Prefetch精准预取每个评论用户针对该Poller的投票记录。这样可以避免N+1查询问题,性能更优:

先导入需要的模块:

from django.contrib.comments.models import Comment
from django.contrib.contenttypes.models import ContentType
from django.db.models import Prefetch

然后更新视图代码:

@require_GET
def single_poller(request, poller_id):
    """ renders a specific poller with prepopulated meta according to previous user interaction, e.g. votes and likes """
    # Retrieve the item via get
    poller = Poller.objects.get(poller_id=poller_id)
    
    # 获取当前Poller对应的ContentType(django-contrib-comments用这个关联目标模型)
    poller_ct = ContentType.objects.get_for_model(Poller)
    
    # 获取该Poller下的所有评论,同时预取每个评论用户的对应投票
    comments = Comment.objects.filter(
        content_type=poller_ct,
        object_pk=str(poller.poller_id)  # 因为主键是UUID,要转成字符串匹配Comment的object_pk字段
    ).prefetch_related(
        # 预取评论用户针对当前Poller的投票,存到poller_vote属性里
        Prefetch(
            'user__vote',
            queryset=Vote.objects.filter(poller=poller),
            to_attr='poller_vote'
        )
    )
    
    # 把poller和comments传到模板
    context = {
        'poller': poller,
        'comments': comments,
        # 其他你需要的上下文变量...
    }
    return render(request, 'your_template.html', context)

第三步:在模板中渲染评论与投票信息

现在模板里就能直接拿到每个评论用户的投票记录了,因为我们已经把投票预取到了comment.user.poller_vote里(因为加了unique约束,这个列表里最多只有一个元素):

{% for comment in comments %}
    <div class="comment-card">
        <h4>{{ comment.user.username }}</h4>
        <p class="comment-content">{{ comment.comment }}</p>
        
        {% with user_vote=comment.user.poller_vote.0 %}
            {% if user_vote %}
                <p class="vote-info">
                    该用户投票选择:
                    {% if user_vote.poller_choice_one_vote %}
                        选项一
                    {% elif user_vote.poller_choice_two_vote %}
                        选项二
                    {% endif %}
                </p>
            {% else %}
                <p class="vote-info">该用户未参与此投票</p>
            {% endif %}
        {% endwith %}
    </div>
{% endfor %}

为什么不用子类化CommentAbstractModel?

因为你的Comment模型(不管是默认的还是自定义的子类)已经通过user字段关联到了Account,而Vote同时关联了Account和Poller——这就形成了Comment -> User -> Vote <- Poller的关联链,通过预取关联查询完全可以拿到需要的数据,根本不需要修改第三方库的模型结构,完美符合你的需求。

内容的提问来源于stack exchange,提问作者JSRB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:57:35