django-admin:添加额外的行总计

Cla*_*diu 30 python django django-admin django-views django-1.2

我正在使用标准的django管理模块来显示行列表.其中一列是数字字段.我想显示一个额外的'总计'行,其中大部分列都是空白的,除了数字列,它应该是所有对象的总和.

在管理模块中是否有一种简单的方法可以做到这一点,或者我最好为它制作自定义视图?

我正在使用Django 1.2.

Fal*_*gel 31

是的,你可以通过多种方式实现,但大多数django-ist方法是:

首先覆盖默认的django列表视图...并给出一个新的模板文件目录

ModelAdmin.changelist_view(self, request, extra_context=None)
Run Code Online (Sandbox Code Playgroud)

喜欢:

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)
Run Code Online (Sandbox Code Playgroud)

因此,您将列表视图上下文添加为"总计",以保留总值并将其传递给模板.

如果设置了change_list_template,则django使用该模板,否则,它使用标准的django模板.

如果调用def changelist_view(self,request,extra_context = None),则django使用该函数创建内容,否则使用默认的django视图.

然后创建一个admin/myapp/extras/sometemplate_change_form.html文件并将您放置{{total}}到您想要的任何位置.

如何覆盖管理模板的指南以下 是如何覆盖管理员视图

更新:我添加一个简单aggregate的计算总数.您可以编辑它以根据需要进行设置.

更新2:从固定的ModelAdmin模板覆盖选项ModelAdmin.change_form_templateModelAdmin.change_list_template.(谢谢c4urself).是的,但更改默认的django管理模板是一个非常糟糕的选择,因为它被许多其他ModelAdmin使用,如果更新相关模板,它可能会导致问题.



注意:
使用过滤器时总计不会改变,请参阅下面的评论.

  • 甜,这真的是我正在寻找的复制粘贴配方.我只是说,不是在Admin类上配置`change_list_template`,而是创建一个文件,如:`templates/admin/my_app/my_model/change_list.html`,然后在该文件中只使用`{%extends' admin/change_list.html'%}`,只覆盖一个块,如:`{%block result_list%} {{block.super}} <p>总计是:{{total}} !!! </ p> {%endblock%}`.约定配置;) (3认同)
  • 我认为这是一个很好的方法,我相信`change_form_template`应该是`change_list_template`.如果您覆盖管理模板,则根本不需要为其指定模板名称. (2认同)

c4u*_*elf 26

我认为Django这样做的方法是覆盖django管理员应用程序使用的ChangeList类.您可以通过调用get_changelist管理类中的方法在django 1.2中执行此操作.在我的示例中:TomatoAdmin调用此方法返回自定义ChangeList calss.这个ChangeList类:MyChangeList只是为上下文添加一个额外的属性change_list.html.

确保change_list.html位于以下目录中:

app_label/change_list.html
Run Code Online (Sandbox Code Playgroud)

在示例中,这是:templates/admin/tomato/change_list.html

models.py(带整数字段的简单模型)

class CherryTomato(models.Model):
    name = models.CharField(max_length=100)
    num_in_box = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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 %}
Run Code Online (Sandbox Code Playgroud)

我会告诉你如何以你想要的方式设计它.


Fat*_*man 7

好的,所以有一种方法可以做到这一点,包括添加几个新的模板标签和扩展管理模板.

首先,在应用程序的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)
Run Code Online (Sandbox Code Playgroud)

然后,您需要所有行的模板myapp/totals_row.html(模板所在的位置):

<table id="result_totals">
    <tfoot>
        <tr>
            {% for total in totals_row %}<td>{{ total }}</td>{% endfor %}
        </tr>
    </tfoot>
</table>
Run Code Online (Sandbox Code Playgroud)

然后,您需要将其连接到继承自Django默认的自定义管理模板,例如myapp/mymodel_admin.html:

{% extends "admin/change_list.html" %}

{% load admin_totals %}

{% block result_list %}
{{ block.super }}
{% totals_row cl %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

最后,您将其连接到admin.py应用程序文件中的配置:

class MyModelAdmin(ModelAdmin):

    list_display = ('name', 'date', 'numerical_awesomeness')
    total_functions = {'numerical_awesomeness': sum}

    change_list_template = 'myapp/mymodel_admin.html'
Run Code Online (Sandbox Code Playgroud)

这应该连接到新模型的自定义管理模板,显示总计行.如果sum您愿意,也可以使用除其他摘要功能之外的其他摘要功能进行扩展.

剩下一小点:总计行实际上并不在结果表中,因为这需要对Django管理模板进行一些相当粗糙的复制和粘贴.对于奖励积分,您可以将以下微笑的JavaScript添加到totals_row.html文件的底部:

<script type="text/javascript">
    django.jQuery('#result_list').append(django.jQuery('#result_totals tfoot')[0])
    django.jQuery('#result_totals').remove()
</script>
Run Code Online (Sandbox Code Playgroud)

一个警告:所有这些只会反映当前显示的项目的总数,而不是现有的所有项目.解决这个问题的一种方法是,如果你不介意潜在的性能影响,你可以list_per_pageModelAdmin课堂上设置一些不可思议的大数字.


小智 7

这个线程持续了一段时间,但我可能不是最后一个正在寻找这种功能的人。因此,我创建了一个易于添加总计的软件包。

结帐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)]
Run Code Online (Sandbox Code Playgroud)

随意分叉并进行改进。


Eva*_*ley -3

据我所知,如果不创建自定义视图,就无法做到这一点。无论如何,这个概念有点缺陷,因为用户希望这样的行仅显示可见对象的总数,而不是查询集中所有对象的总数。因此,任何分页都会导致混乱。

另外,您可以通过执行以下操作向管理列表视图添加额外的列:

class ItemAdmin(admin.ModelAdmin):
    model = Item

    list_display = ('field1', 'field2', 'extra_field')

    def extra_field(self, obj):
        return u'%s' % do_something_with(obj)
Run Code Online (Sandbox Code Playgroud)