Django减少了查询

时间:2017-02-17 14:05:29

标签: python mysql django

我有两个模型,Post和Vote。用户可以投票和投票。

models.py:

class Post(models.Model):
    poster = models.ForeignKey('auth.User')
    question = models.ForeignKey('self', null=True, blank=True)
    post_title = models.CharField(max_length=300)
    post_content = models.TextField(null=True, blank=True)

    is_published = models.BooleanField(default=True)
    is_locked = models.BooleanField(default=False)
    is_question = models.BooleanField(default=True)
    is_deleted = models.BooleanField(default=False)

    created_date = models.DateTimeField(
            default=timezone.now)
    published_date = models.DateTimeField(
            blank=True, null=True)
    date_modified = models.DateTimeField(
            blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.post_title

class Vote(models.Model):
    user = models.ForeignKey('auth.User')
    post = models.ForeignKey('Post')
    vote_type = models.SmallIntegerField()#-1, 0, 1
    date_voted = models.DateTimeField(
            default=timezone.now)
    def __str__(self):
        return self.user

我在视图中使用以下代码将帖子返回给模板:

views.py:

def index(request):
    posts = Post.objects.filter(created_date__lte=timezone.now(
    ), is_question=1, is_published=1).order_by('-created_date')
    #removed the paging stuff here for simplification
    return render(request, 'homepage/index.html', {'posts': posts})

这只是返回帖子,但我也想检查当前用户是否已经投票(并且可能是每个帖子的vote_type列的总和,即该帖子的总投票数)。

目前,我为每个帖子使用模板标签来检查当前用户是否已投票。这会产生很多查询。 (目前有50个查询,有40个重复)。

我的index.html示例代码:

{% for post in posts %}
       {% if post|userVotedThisPost:request.user.id == 1 %}
               <img id="upvote-img" class="icons" src="{% static 'img/upvote-marked.svg' %}" alt="Upvote">
       {% else %}
               <img id="upvote-img" class="icons" src="{% static 'img/upvote.svg' %}" alt="Upvote">
       {% endif %}
{% endfor %}

有没有办法查询views.py中的所有内容,然后在模板中我可以像这样检查:(如果是post.user_voted),这样每次在for循环中都不会命中数据库?

1 个答案:

答案 0 :(得分:3)

您可以使用prefetch_related来获取该用户的相关投票。

from django.db.models import Prefetch

Post.objects.filter(
    created_date__lte=timezone.now(),
    is_question=1, 
    is_published=1
).order_by(
    '-created_date',
).prefetch_related(
    Prefetch('vote_set', queryset=Vote.objects.filter(user=request.user), to_attr='user_votes')
)

然后在您的模板中,将检查更改为:

{% if post.user_votes %}