我正在建立一个以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>
答案 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 }}
该方法在项目的其他地方也很有用。您可能希望在多个位置执行仅发布注释的相同逻辑。