Django-admin: добавьте дополнительную строку с итогами
Я использую стандартный модуль администратора django для отображения списка строк. Один из столбцов - это числовое поле. Я бы хотел отобразить дополнительную строку "totalals", которая содержит большинство столбцов как пустую, за исключением числового столбца, который должен быть общим для всех объектов.
Есть ли простой способ сделать это в модуле администратора, или мне лучше создать для него пользовательский вид?
Я использую Django 1.2.
Ответы
Ответ 1
Да, вы можете сделать это разными способами, но большинство способов django-ist:
Сначала переопределите представление списка django по умолчанию... И дайте новый каталог файлов шаблонов
ModelAdmin.changelist_view(self, request, extra_context=None)
Как
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_list_template = 'admin/myapp/extras/sometemplate_change_form.html'
def get_total(self):
#functions to calculate whatever you want...
total = YourModel.objects.all().aggregate(tot=Sum('total'))['tot']
return total
def changelist_view(self, request, extra_context=None):
my_context = {
'total': self.get_total(),
}
return super(MyModelAdmin, self).changelist_view(request,
extra_context=my_context)
Итак, вы добавляете в контекст вида списка 'total', который сохраняет ваше общее значение и передает его в шаблон.
если change_list_template будет установлен, django использует этот шаблон, в противном случае он использует стандартный шаблон django.
Если вызывается def changelist_view (self, request, extra_context = None), django использует эту функцию для создания контента, в противном случае он использует представления django по умолчанию.
Затем создайте файл admin/myapp/extras/sometemplate_change_form.html
и поместите свой {{total}}
в любое место.
Руководство по переопределить шаблоны администратора
И вот как переопределить представления администратора
UPDATE: Я добавляю простой aggregate
для вычисления общего количества. вы можете отредактировать его, чтобы установить его в соответствии с вашими потребностями.
ОБНОВЛЕНИЕ 2: опция переопределения шаблона ModelAdmin исправлена с ModelAdmin.change_form_template
до ModelAdmin.change_list_template
. (спасибо вам c4urself). Да, но изменение шаблона администратора django по умолчанию - очень плохой выбор, поскольку он используется многими другими ModelAdmin, и это может вызвать проблемы при обновлении связанных шаблонов.
NB:
При использовании фильтров Total не изменяется, см. Комментарий ниже.
Ответ 2
Я думаю, что способ Django сделать это - переопределить класс ChangeList, который использует приложение администратора django. Вы делаете это в django 1.2, вызывая метод get_changelist
в вашем классе администратора. В моем примере: TomatoAdmin
вызывает этот метод, возвращающий настраиваемые CALS списка изменений. Этот класс ChangeList: MyChangeList
просто добавляет дополнительный атрибут в контекст change_list.html
.
Убедитесь, что файл change_list.html находится в следующем каталоге:
app_label/change_list.html
в примере: шаблоны /admin/tomato/change _list.html
models.py (простая модель с целочисленным полем)
class CherryTomato(models.Model):
name = models.CharField(max_length=100)
num_in_box = models.IntegerField()
admin.py (ваш класс Admin и пользовательский класс ChangeList)
from django.contrib import admin
from django.contrib.admin.views.main import ChangeList
from django.db.models import Count, Sum
from tomatoes.tomato.models import CherryTomato
class MyChangeList(ChangeList):
def get_results(self, *args, **kwargs):
super(MyChangeList, self).get_results(*args, **kwargs)
q = self.result_list.aggregate(tomato_sum=Sum('num_in_box'))
self.tomato_count = q['tomato_sum']
class TomatoAdmin(admin.ModelAdmin):
def get_changelist(self, request):
return MyChangeList
class Meta:
model = CherryTomato
list_display = ('name', 'num_in_box')
admin.site.register(CherryTomato, TomatoAdmin)
change_list.html (только соответствующий бит, скопируйте/вставьте существующий и продолжите его)
{% block result_list %}
{% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}
{% result_list cl %}
{% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}
Tomatoes on this page: {{ cl.tomato_count }}
{% endblock %}
Я оставлю это вам, как это сделать так, как вы хотите.
Ответ 3
Хорошо, поэтому есть способ сделать это, включая добавление в пару новых тегов шаблонов и расширение шаблонов администратора.
Во-первых, в папке приложений templatetags
вы создаете файл admin_totals.py
, содержащий тег шаблона, чтобы создать итоговую строку:
from django.template import Library
register = Library()
def totals_row(cl):
total_functions = getattr(cl.model_admin, 'total_functions', {})
totals = []
for field_name in cl.list_display:
if field_name in total_functions:
values = [getattr(i, field_name) for i in cl.result_list]
totals.append(total_functions[field_name](values))
else:
totals.append('')
return {'cl': cl, 'totals_row': totals}
totals_row = register.inclusion_tag("myapp/totals_row.html")(totals_row)
Затем вам понадобится шаблон для указанной строки в myapp/totals_row.html
(где бы ни были ваши шаблоны):
<table id="result_totals">
<tfoot>
<tr>
{% for total in totals_row %}<td>{{ total }}</td>{% endfor %}
</tr>
</tfoot>
</table>
Затем вам нужно подключить это к настраиваемому шаблону администратора, наследующему от Djangos по умолчанию, например myapp/mymodel_admin.html
:
{% extends "admin/change_list.html" %}
{% load admin_totals %}
{% block result_list %}
{{ block.super }}
{% totals_row cl %}
{% endblock %}
Наконец, вы подключаете это в конфигурацию вашего файла admin.py
в своем приложении:
class MyModelAdmin(ModelAdmin):
list_display = ('name', 'date', 'numerical_awesomeness')
total_functions = {'numerical_awesomeness': sum}
change_list_template = 'myapp/mymodel_admin.html'
Это должно быть связано с настраиваемым шаблоном администратора для вашей новой модели, отображающим итоговую строку. Вы также можете расширить его с помощью других суммарных функций, отличных от sum
, если вы этого пожелаете.
Осталась одна маленькая точка: итоговая строка не находится в таблице результатов, потому что для этого потребуется довольно грубое копирование и вставка шаблонов администратора Django. Для бонусных очков вы можете добавить в нижнем конце вашего файла totals_row.html
следующий smidge JavaScript:
<script type="text/javascript">
django.jQuery('#result_list').append(django.jQuery('#result_totals tfoot')[0])
django.jQuery('#result_totals').remove()
</script>
Одно предостережение: все это будет отражать только итоговые значения для отображаемых в настоящее время элементов, а не для всех существующих объектов. Один из способов заключается в том, чтобы установить list_per_page
на какое-то неоправданно большое число в вашем классе ModelAdmin
, если вы не возражаете против потенциального повышения производительности.
Ответ 4
Существует также пакет "django-admin-changelist-stats", который может предоставлять сводную статистику. Я успешно использовал его в проекте Django 1.6.
IMO использует решение c4urself для тонкой настройки шаблона, но если его единственные агрегаты (сумма/avg/min/max) таблиц, которые вы после этого, это решение довольно хорошо.
С веб-сайта
"
Это простое приложение обеспечивает статистику и возможности агрегации для просмотра списков администратора Django.
Это позволяет легко отображать статистику в конце страницы списка изменений, просто добавляя один параметр к объекту admin.
"
Дополнительная информация, включая примеры, на веб-странице репозитория bitbucket
https://bitbucket.org/frankban/django-admin-changelist-stats/src
Ответ 5
если вы создаете настраиваемое представление, переопределяющее представление администратора, вы можете взять запрос и вместе с текущей информацией о странице и разрезать данные, чтобы создать общее соответствие текущей странице. если вы хотите получить истинную сумму, но я все еще вижу пользовательский переопределенный вид администратора в качестве опции, которую вы ищете.
Ответ 6
Этот поток продолжается некоторое время, но я, вероятно, не последний, который ищет такую функцию. Поэтому я создал пакет, который упрощает добавление итогов.
Оформить заказ https://github.com/douwevandermeij/admin-totals
Использование:
from admin_totals.admin import ModelAdminTotals
from django.contrib import admin
from django.db.models import Sum, Avg
@admin.register(MyModel)
class MyModelAdmin(ModelAdminTotals):
list_display = ['col_a', 'col_b', 'col_c']
list_totals = [('col_b', Sum), ('col_c', Avg)]
Не стесняйтесь разветвлять его и улучшать.
Ответ 7
AFAIK нет способа сделать это без создания пользовательского представления. В любом случае эта концепция немного испорчена, потому что пользователь будет ожидать, что такая строка будет показывать общее количество только для видимых объектов, а не для всех объектов в наборе запросов. Таким образом, любая разбивка на страницы приведет к путанице.
Как и в стороне, вы можете добавить дополнительные столбцы в представление списка администратора, выполнив следующие действия:
class ItemAdmin(admin.ModelAdmin):
model = Item
list_display = ('field1', 'field2', 'extra_field')
def extra_field(self, obj):
return u'%s' % do_something_with(obj)