Django 自定义模板标签

Django custom template tags

为什么我的自定义模板标签不起作用?

templatetags.py:

    from django import template
    from ..models import User

    register = template.Library()


    @register.inclusion_tag('main/post_detail.html', takes_context=True)
    def get_user_liked_posts():
        request = context['request']
        user = User.objects.get(username=request.user.username)
        liked_posts = []
        for post in user.liked_posts.all():
            liked_posts.append(post.name)
        return {'liked_posts': liked_posts}

post_detail.html:

{% load static %}
{% load templatetags %}

<nav class="blog-pagination" aria-label="Pagination">
    <span id="likes_count">{{ post.likes_count }}</span>
        {% if post.name in liked_posts %}
            <button id="like_button" class="btn btn-outline-primary btn-primary text-        
                    white">Like</button>
        {% else %}
            <button id="like_button" class="btn btn-outline-primary">Like</button>
        {% endif %}
</nav>

views.py:

    class PostDetailView(DetailView):
        model = Post
        slug_field = 'url'


    class LikePostView(View):

        def post(self, request, slug):
            post = Post.objects.get(id=request.POST['id'])
            user = User.objects.get(username=request.user.username)

            if request.POST['like'] == 'true':
                post.likes_count += 1
                user.liked_posts.add(post)
            else:
                post.likes_count -= 1
                user.liked_posts.remove(post)
            user.save()
            post.save()
            return redirect('post_detail', slug)

models.py:

class Post(models.Model):
    """
    This is post model
    """
    name = models.CharField(max_length=150, blank=False)
    article = models.TextField(blank=False)
    image = models.ImageField(upload_to='uploads/', blank=True)
    likes_count = models.IntegerField(default=0)
    url = models.CharField(max_length=150, blank=False)

    def get_absolute_url(self):
        return reverse('post_detail', kwargs={'slug': self.url})

我想查看post是否在当前用户的已点赞post中,但是没有用。 它没有显示任何错误,只是什么都不做。 我的应用中的用户必须喜欢或不喜欢 posts。在模型中,我与 post 有多对多的关系用户。我想检查用户是否喜欢这个 post

问题是你甚至没有使用模板标签,而且甚至不需要这个,因为你可以简单地在模板中写这样的东西:

{% if post in request.user.liked_posts.all %}
    A Liked post
{% else %}
    Not a liked post
{% endif %}

但这有点低效,因为我们获取用户喜欢的所有 post 只是为了检查他们是否喜欢某些 post。此外,如果这是一个包含多个 post 的循环,我们将对每个 post.

进行查询

相反,我们可以在多对多的 through 模型上使用 Exists subquery [Django docs] 在视图本身中简单地注释用户是否喜欢 post:

from django.db.models import Exists, OuterRef


class PostDetailView(DetailView):
    model = Post
    slug_field = 'url'
    
    def get_queryset(self):
        queryset = super().get_queryset()
        queryset = queryset.annotate(
            liked_by_user=Exists(
                User.liked_posts.through.objects.filter(
                    post_id=OuterRef("pk"),
                    user_id=self.request.user.id
                )
            )
        )
        return queryset

现在在模板中我们可以简单的写:

{% if post.liked_by_user %}
    A Liked post
{% else %}
    Not a liked post
{% endif %}

Note: Your way of saving the count similarly can simply be turned into an annotation using the Count aggregation function [Django docs]. Generally one should not store calculated attributes in a column since that might lead to inconsistent data when updating and forgetting to update the related count, etc.