django - Counting all items linked to foreign key
问题描述
I'm looking for a solution to combine in one view information from two models. One model is for "node" definition. Second model is "drive" definition, where I have foreign key for "node". One "node" can contain many drives. In a template I need to show all assigned drives for a given node in a list view. I'm interested in count, a number of drives assigned to given node.
I don't have any new idea how calculate this information and pass to template. Should I count this as a "pure python"? I believe there is a way in Django as this doesn't look very complex.
View:
class NodeListView(ListView):
template_name = 'nodes/nodes_list.html'
queryset = Node.objects.all()
context_object_name = 'nodes'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
drives = Drive.objects.all()
context.update({
'drives': drives
})
return context
Models:
class Node(models.Model):
name = models.CharField(max_length=32)
.... more ....
class Drive(models.Model):
node = models.ForeignKey(Node, related_name='nodes', on_delete=models.CASCADE)
.... more ....
解决方案
Node
您可以使用相关 s 的数量来注释Drive
s:
from django.db.models import Count
class NodeListView(ListView):
template_name = 'nodes/nodes_list.html'
queryset = Node.objects.annotate(ndrives=Count('nodes'))
context_object_name = 'nodes'
然后您可以使用以下方法渲染它:
{% for node in nodes %}
{{ node.ndrives }}
{% endfor %}
您还可以使用以下方法枚举相关 Drive
的 s:
{% for node in nodes %}
{{ node.ndrives }}
{% for drive in node.nodes.all %}
{{ drive }}
{% endfor %}
{% endfor %}
您可以通过以下方式提高效率:
from django.db.models import Count
class NodeListView(ListView):
template_name = 'nodes/nodes_list.html'
queryset = Node.objects.annotate(
ndrives=Count('nodes')
).prefetch_related('nodes')
context_object_name = 'nodes'
之所以这样命名nodes
,是因为related_name='nodes'
. 然而,这没有多大意义:related_name='drives'
会更有意义,因为它处理Drive
s 的集合,因此您可能希望将其重命名为:
class Node(models.Model):
name = models.CharField(max_length=32)
# …
class Drive(models.Model):
node = models.ForeignKey(
Node,
related_name='drives',
on_delete=models.CASCADE
)
# …
然后视图看起来像:
from django.db.models import Count
class NodeListView(ListView):
template_name = 'nodes/nodes_list.html'
queryset = Node.objects.annotate(
ndrives=Count('drives')
).prefetch_related('drives')
context_object_name = 'nodes'
我们用以下方式渲染它:
{% for node in nodes %}
{{ node.ndrives }}
{% for drive in node.drives.all %}
{{ drive }}
{% endfor %}
{% endfor %}
推荐阅读
- azure-devops - Azure Dev Ops - 如何要求 3 个批准者中的 2 个进行部署前批准?
- php - PHP - 如果路由返回字符串,则不进入循环
- javascript - 如何在express node.js中发送对ajax post请求的响应?[已回答]
- c# - Unity ARKit SetWorldOrigin - 旋转错误
- sequelize.js - 在 Sequelize 中比较日期
- excel-formula - COUNTIFS 在排序数据中显示错误的输出
- angular - 使用 webpack/bin/config-yargs 迁移 Angular 7 时出现问题
- java - 组合框条目未显示在框架上
- python - 如何在 Python 中使用 .split 将未知数量的数字输入分配给变量?
- django - Django 框架表单正在尝试插入新记录而不是更新