2010-10-23 97 views
1

我不时需要用Django编写一些简单的摘要报告。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原则。

我看了一下“Geraldo报告”,但它不是“一见钟情”。

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

回答

0

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

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) 
0

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

+0

组摘要打印在每个组的最后一行之后,因为循环结束,最后一行不会被打印。 – 2010-10-23 23:23:35