(Django)如何将列表中的动态对象的查询集计数添加到模板中?

时间:2018-03-03 21:17:14

标签: python django templatetags

我正在建立一个以django作为存放我的大学笔记的地方的网站。

我有一个笔记模型,它由foreignkey链接到类别模型。

在我的主页上,我使用for循环发布每个类别页面的链接,但在括号中我还想显示该类别中已发布的笔记数。

例如:

生物学(6) 化学(4) 物理学(12)

等等

我使用模板标签来给出长度,例如。 for循环中的{{category.notes_set.all | length}}显示类别中的备注数量,但这会忽略是否已发布备注或是否刚刚创建备注。如果我有6个已发布和1个未发布的注释,它将给出值7 - 我希望它显示6.我真的想要过滤(published_date__lte = timezone.now())但不认为这可以在模板中实现。

我是否必须为每个类别创建一个上下文字典,并使用视图中的计数对其进行注释?我觉得当类别和子类别的数量变得非常大时,这将是难以管理的。我可以在views.py中使用for循环吗?

很抱歉,如果这有明显的答案,我是一个真正的初学者。

最近的编辑:似乎最优雅的解决方案是根据Ben的回答在models.py中为我的模型类添加一个函数。因此,对于案例研究登陆页面,我添加了:

def published_cases(self):
    return self.case_set.filter(published_date__lte=timezone.now())

到我的专业模特。然后我将{{specialty.published_cases.all | length}}添加到我的模板中。

感谢大家的帮助。

编辑:我正在尝试将注释函数合并到基于类的视图中。以下是我的案例研究登陆页面的一些示例代码。它显示了一个新案例研究列表,最受好评的案例研究和一系列专业,我希望通过发表的案例研究进行注释。我尝试了以下代码:

class CaseListView(TemplateView):
template_name = "case_list.html"

def get_context_data(self, **kwargs):
    context = super(CaseListView, self).get_context_data(**kwargs)
    context["cases"] = Case.objects.filter(published_date__lte=timezone.now()).order_by("-published_date")[:5]
    context["topcases"] = Case.objects.filter(published_date__lte=timezone.now()).annotate(num_upvotes=Count("upvotes")).order_by("-num_upvotes")[:5]
    context["specialtys"] = Specialty.objects.all().order_by("name").annotate(num_cases=Count("case", filter=Q(case__published_date__lte=timezone.now())))
    return context

这给了我一个NameError(异常值:名称'Q'未定义)。

我尝试了另一种构建上下文的方法:

context["specialtys"] = Specialty.objects.all().order_by("name").annotate(num_cases=Count("case")).filter(case__published_date__lte=timezone.now())

这没有引发异常,但没有给出理想的结果,给{{specialty.num_cases}}一个非常不正确的值,凭借我的知识水平,我甚至无法想象它是如何计算的。 / p>

2 个答案:

答案 0 :(得分:0)

您需要使用aggregation。在您的视图中,您可以使用相关注释的计数对每个类别进行注释,仅将计数过滤为已发布的注释。

from django.db.models import Count, Q
categories = Category.objects.annotate(note_count=Count("note", filter=Q(note__published_date__lte=timezone.now())))

现在每个类别都有一个属性note_count,其中包含已发布的笔记数。

答案 1 :(得分:0)

您可以向仅返回已发布笔记的类别模型添加方法:

class Category(models.Model):
    ... model definition ...

    def published_notes(self):
        return self.notes_set.filter(published_date__lte=timezone.now())

然后在模板中使用它:

{{ category.published_notes|length }}

该方法在项目的其他地方也很有用。您可能希望在多个位置执行仅发布注释的相同逻辑。