【问题标题】:Summary tag for django templatesdjango 模板的摘要标签
【发布时间】:2010-10-23 20:13:39
【问题描述】:

有时我不得不使用 Django 编写一些简单的总结报告。

首先我尝试使用 Django ORM 聚合和交错结果,但它可能会变得有点混乱,并且我失去了所有 ORM 懒惰 - 感觉不对。

最近我编写了一个可以对数据集进行分组/汇总的通用迭代器类。在视图中它的工作方式如下:

s_data = MyIterator(dataset, group_by='division', \
                                   sum_fields=[ 'sales', 'travel_expenses'])

在模板中它的工作方式如下:

{% for g, reg in s_data %}
    {% if g.group_changed %}
        <tr><!-- group summary inside the loop --> 
            <td colspan="5">{{ g.group }} Division</td>
            <td>{{ g.group_summary.sales }}</td>
            <td>{{ g.group_summary.travel_expenses }}</td>
        </tr>
    {% endif %}
    <tr><!-- detail report lines -->
        <td>{{ reg.field }}<td>
        <td>{{ reg.other_field_and_so_on }}<td>
        ...
    </tr>
{% endfor %}
<tr><!-- last group summary -->
    <td colspan="5">{{ s_data.group }} Division</td>
    <td>{{ s_data.group_summary.sales }}</td>
    <td>{{ s_data.group_summary.travel_expenses }}</td>
</tr>
<tr>
    <td colspan="5">Total</td>
    <td>{{ s_data.summary.sales }}</td>
    <td>{{ s_data.travel_expenses }}</td>
</tr>

我认为它比我以前的方法优雅得多,但是必须重复最后一组摘要的代码违反了 DRY 原则。

我看过“杰拉尔多报道”,但不是“一见钟情”。

为什么没有组/摘要模板标签,我应该写一个吗?

【问题讨论】:

    标签: django django-templates reporting


    【解决方案1】:

    我可能错过了一些就在我面前的东西,但是为什么你有最后一组在循环之外?

    【讨论】:

    • 分组汇总在每组最后一行之后打印,最后一个不会打印,因为循环结束了。
    【解决方案2】:

    我想通了,它可以用迭代器完成,不需要模板标签。诀窍是延迟迭代一个周期。

    class GroupSummaryIterator(object):
        """GroupSummaryIterator(iterable, group_by, field_list)
    
    - Provides simple one level group/general summary for data iterables.
    - Suports both key and object based records
    - Assumes data is previously ordered by "group_by" property *before* use
    
    Parameters:
    ===========
      iterable: iterable data
      group_by: property or key name to group by
    field_list: list of fileds do sum
    
    Example:
    ======
    data =  [{'label': 'a', 'field_x': 1, 'field_c': 2},
             {'label': 'a', 'field_x': 3, 'field_c': 4},
             {'label': 'b', 'field_x': 1, 'field_c': 2},
             {'label': 'c', 'field_x': 5, 'field_c': 6},
             {'label': 'c', 'field_x': 1, 'field_c': 2}]
    
    s = GroupSummaryIterator(data, 'label', ['field_x', 'field_c'])
    for x,y in s:
         print y
         if x['group_changed']:
             print x['group'], 'summary:', x['group_summary']
    print 'general summary:', s.summary
    
        """
        def __init__(self, iterable, group_by, field_list):
            self.iterable = iterable
            self.group_by = group_by
            self.field_list = field_list
        def _a(self, obj, key):
            """Get property or key value"""
            if isinstance(key, basestring) and hasattr(obj, key):
                return getattr(obj, key)
            try:
                return obj[key]
            except:
                return None
        def _sum(self, item):
            if self.group_changed:
                self.cur_summary = dict()
            for field in self.field_list:
                value = self._a(item, field)
                if not value:
                    value = 0.0
                else:
                    value = float(value)
                if self.summary.has_key(field):
                    self.summary[field] += value
                else:
                    self.summary[field] = value
                if self.cur_summary.has_key(field):
                    self.cur_summary[field] += value
                else:
                    self.cur_summary[field] = value
        def _retval(self, item, summary):
            """If each item from the source iterable is itself an iterable, merge
            everything so you can do "for summ, a, b in i" where you would have
            done "for a, b in i" without this object."""
            if isinstance(item, dict):
                retval = (item,)
            else:
                try:
                    retval = tuple(item)
                except:
                    retval = (item,)
            return (dict(group_changed=self.group_changed, group=self.group, group_summary=summary),) + retval
        def __iter__(self):
            self.cur_group = None
            self.group = None
            self.finished = False
            self.group_changed = False
            self.cur_item = None
            self.last_item = None
            self.summary = dict()
            self.group_summary = dict()
            self.cur_summary = dict()
            for item in self.iterable:
                self.group = self.cur_group
                self.group_summary = self.cur_summary
                self.cur_group = self._a(item, self.group_by)
                self.group_changed = self.group and self.cur_group != self.group
                self.last_item = self.cur_item
                self.cur_item = item
                self._sum(item)
                if self.last_item is None:
                    continue
                yield self._retval(self.last_item, self.group_summary)
            if self.cur_item:
                self.group_changed = True
                yield self._retval(self.cur_item, self.group_summary)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-18
      • 1970-01-01
      • 2011-02-09
      • 2012-10-31
      • 2018-10-21
      • 2014-03-20
      • 2014-07-25
      • 2014-04-03
      相关资源
      最近更新 更多