我正在努力设计django应用程序。鉴于以下模型:
class A(models.Model):
name = models.CharField(max_length=255)
class B(models.Model):
name = models.CharField(max_length=255)
a = models.ForeignKey(A)
class C(models.Model):
val = models.IntegerField()
b = models.ForeignKey(B)
我想要一个显示HTML表格的视图/模板,在第一列中显示所有A对象,在第二列中显示所有B对象(按A分组)引用A和最后一列中的总和每个参考每个B的C对象的所有val。所有这些都包含每个A对象的总和。 以下示例显示了我正在寻找的内容:
A1.name | B1.name [where FK to A1] | sum(C.val) [where FK to B1] A1.name | B2.name [where FK to A1] | sum(C.val) [where FK to B2] A1.name | Total | sum(C.val) [where FK to Bx (all B that have FK to A1] A2.name | B3.name [where FK to A2] | sum(C.val) [where FK to B3] A2.name | Total | sum(C.val) [where FK to Bx (all B that have FK to A2]
任何人都可以给我一个如何设计这样一个问题的建议(不幸的是,我的代码经常会乱七八糟)?
我应该使用适当的方法扩展模型类吗?在视图中对整个表数据执行自定义查询?只需通过经理获取所有对象并完成模板中的大部分工作吗?
感谢您的每一个答案。
此致
路。
答案 0 :(得分:6)
如果您有该日期模型,那么您可以获取所有b
,然后按a
对其进行分组并计算总金额。代码可能如下所示:
查看:
from django.utils.itercompat import groupby
def view(request):
bs = B.objects.all().annotate(sum_of_c_val=Sum('c.val'))\
.select_related('a')
b_by_a = [
{
'grouper': key,
'list': list(val),
'total': sum([b.sum_of_c_val for b in val])
}
for key, val in
groupby(bs, lambda b: b.a)
]
return render_to_response('tmpl.html', {'b_by_a': b_by_a})
模板:
{% for b_group in b_by_a %}
{% for b in b_group.list %}
<tr>
<td>{{b_group.grouper.name}}</td>
<td>{{b.name}}</td>
<td>{{b.sum_of_c_val}}</td>
</tr>
{% endfor %}
<tr>
<td>{{b_group.grouper.name}}</td>
<td>Total</td>
<td>{{b_group.total}}</td>
</tr>
{% endfor %}
修改强>
为了与Django 1.0兼容,你必须用annotate
select或in-python amount计算来替换extra
调用。
使用子查询:
bs = B.objects.all().extra(
select={
'sum_of_c_val': 'SELECT SUM(app_c.val) FROM app_c WHERE app_c.b_id=app_b.id'
}).select_related('a')
#...
app
- 申请名称
这个in-python计算:
bs = B.objects.all().select_related('a')
for b in bs:
b.sum_of_c_val = sum(map(int, b.c.all().values_list("val", flat=True)))
#...
但它会产生N个额外的查询(N = len(bs)
)
答案 1 :(得分:1)
免责声明:我自己是Django初学者,但如果我理解其基本概念,那么:
鉴于您想要的视图 - 正如您所说 - 只是基础数据的视图,那么您应该在视图模块中进行排序和分组。我认为你不应该混淆模型(这只是数据),也不应该模板(这只是视图的布局)。