aggregation.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. from django.db.models import FieldDoesNotExist, Avg, Max, Min, Count, Sum
  2. from django.utils.translation import ugettext as _
  3. from django.forms import Media
  4. from xadmin.sites import site
  5. from xadmin.views import BaseAdminPlugin, ListAdminView
  6. from xadmin.views.list import ResultRow, ResultItem
  7. from xadmin.util import display_for_field
  8. AGGREGATE_METHODS = {
  9. 'min': Min, 'max': Max, 'avg': Avg, 'sum': Sum, 'count': Count
  10. }
  11. AGGREGATE_TITLE = {
  12. 'min': _('Min'), 'max': _('Max'), 'avg': _('Avg'), 'sum': _('Sum'), 'count': _('Count')
  13. }
  14. class AggregationPlugin(BaseAdminPlugin):
  15. aggregate_fields = {}
  16. def init_request(self, *args, **kwargs):
  17. return bool(self.aggregate_fields)
  18. def _get_field_aggregate(self, field_name, obj, row):
  19. item = ResultItem(field_name, row)
  20. item.classes = ['aggregate', ]
  21. if field_name not in self.aggregate_fields:
  22. item.text = ""
  23. else:
  24. try:
  25. f = self.opts.get_field(field_name)
  26. agg_method = self.aggregate_fields[field_name]
  27. key = '%s__%s' % (field_name, agg_method)
  28. if key not in obj:
  29. item.text = ""
  30. else:
  31. item.text = display_for_field(obj[key], f)
  32. item.wraps.append('%%s<span class="aggregate_title label label-info">%s</span>' % AGGREGATE_TITLE[agg_method])
  33. item.classes.append(agg_method)
  34. except FieldDoesNotExist:
  35. item.text = ""
  36. return item
  37. def _get_aggregate_row(self):
  38. queryset = self.admin_view.list_queryset._clone()
  39. obj = queryset.aggregate(*[AGGREGATE_METHODS[method](field_name) for field_name, method in
  40. self.aggregate_fields.items() if method in AGGREGATE_METHODS])
  41. row = ResultRow()
  42. row['is_display_first'] = False
  43. row.cells = [self._get_field_aggregate(field_name, obj, row) for field_name in self.admin_view.list_display]
  44. row.css_class = 'info aggregate'
  45. return row
  46. def results(self, rows):
  47. if rows:
  48. rows.append(self._get_aggregate_row())
  49. return rows
  50. # Media
  51. def get_media(self, media):
  52. return media + Media(css={'screen': [self.static('xadmin/css/xadmin.plugin.aggregation.css'), ]})
  53. site.register_plugin(AggregationPlugin, ListAdminView)