提问者:小点点

为什么条件表达式要向列表视图添加新项


我正在尝试添加一个帖子到一个列表视图,主列表视图已经有一个项目上下文。

在我的项目中,一个用户可以添加一个帖子和添加一个项目每一个都是不同的应用程序与不同的模式。

所以在我的Home列表视图中,我循环了我的项目,在每个项目中,它都显示了与之相关的用户。

我要做的是检查item.user是否有一个与该用户相关的admin_approved=true的帖子,如果确实存在,则页面中会显示一个按钮,该按钮链接到另一个带有这些帖子的页面。

因此,如果没有与用户相关的帖子,或者有帖子可用,但admin_approved=false或尚未admin_approved=true,则不应显示按钮,但如果有1个或更多的帖子是admin_approved=true,则应显示按钮。

我已经尝试注释查询集,但问题是,当一个用户有两个帖子,一个是批准的,另一个不批准,两个项目出现一个有按钮和一个没有按钮,重复发生在主页列表视图

我尝试过使用。distinct(),但它没有工作项仍然是重复的

下面是models.py。

class Post(models.Model):
    designer = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100, unique=True)
    admin_approved = models.BooleanField(default=False)

这里是风景

from .models import Item
from django.db.models import Case, When, BooleanField, Q

class HomeView(ListView):
    model = Item
    paginate_by = 12
    template_name = "home.html"
    ordering = ['-timestamp']

    def get_queryset(self):
        has_post = Case(
            When(Q(designer__post__isnull=False) & Q(designer__post__admin_approved=True), then=True),
            default=False,
            output_field=BooleanField()
        )
        return super().get_queryset().annotate(has_post=has_post).distinct()

这是模板

{% for item in object_list %}
    {{ item.title }}
    {% if item.has_post %}
        SHOW BUTTON
    {% else %}
        HIDE BUTTON
    {% endif %}
{% endfor %}

下面是项目模型

class Item(models.Model):
    designer = models.ForeignKey(
        User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)

共1个答案

匿名用户

它将为每个designer__post组合重复每个item,因为您没有使用“fold”函数。

您可以使用exists子查询[Django-doc]:

from django.db.models import Exists, OuterRef

class HomeView(ListView):
    model = Item
    paginate_by = 12
    template_name = "home.html"
    ordering = ['-timestamp']

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).annotate(
            has_post=Exists(
                Post.objects.filter(
                    designer_id=OuterRef('designer_id'),
                    admin_approved=True
                )
            )
        )