3

我正在努力设计 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 对象,在第二列中显示所有引用 A 的 B 对象(按 A 分组),在最后一列中显示所有 val 的总和每个 B 引用的 C 对象。所有这些都带有每个 A 对象的总和。以下示例显示了我正在寻找的内容:

A1.name | B1.name [其中 FK 到 A1] | sum(C.val) [其中 FK 到 B1]
A1.name | B2.name [其中 FK 到 A1] | sum(C.val) [其中 FK 到 B2]
A1.name | 总计 | sum(C.val) [其中 FK 到 Bx(所有 B 具有 FK 到 A1]
A2.name | B3.name [其中 FK 到 A2] | sum(C.val) [其中 FK 到 B3]
A2.name | 总计 | sum(C.val) [其中 FK 到 Bx(所有具有 FK 到 A2 的 B]

谁能给我一个如何设计这样一个问题的建议(不幸的是,我的代码经常会变得一团糟)?

我应该用适当的方法扩展模型类吗?对视图中的整个表数据进行自定义查询?只需通过管理器获取所有对象并执行模板中的大部分操作?

感谢您的每一个回答。

问候,

卢克。

4

2 回答 2

6

如果您有该日期模型,那么您可以获取所有bs 然后将它们分组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 兼容,您必须将annotatecall替换为extraselect 或 in-python 金额计算。

  1. 使用子查询:

    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')
    #...
    

    Where app- 应用程序名称

  2. 这个 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)

于 2009-02-11T10:56:55.837 回答
1

免责声明:我自己是 Django 初学者,但如果我正确理解了它的基本概念,那么:

鉴于您想要的视图 - 正如您所说 - 只是底层数据的视图,那么您应该在视图模块中进行排序和分组。我认为您不应该弄乱模型(这只是数据),也不应该弄乱模板(这只是视图的布局)。

于 2009-02-11T10:37:57.567 回答