我是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的最佳方法是什么? 我尝试使用用户中间件和模型方法。我也试过预迭代注释,但这与列表使用的递归不一致。
答案 0 :(得分:1)
首先,看起来Comment
是Thread
的超集,换句话说,它们都使用相同的字段,如title
,text
,{{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)