36

行のリストを表示するために、標準の django 管理モジュールを使用しています。列の 1 つは数値フィールドです。すべてのオブジェクトの合計である数値列を除いて、ほとんどの列が空白になっている追加の「合計」行を表示したいと思います。

管理モジュール内でこれを行う簡単な方法はありますか、それともカスタム ビューを作成したほうがよいでしょうか?

私はジャンゴ1.2を使用しています。

4

9 に答える 9

39

はい、さまざまな方法で実行できますが、ほとんどの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)

したがって、リストビューコンテキストに「合計」を追加して、合計値を保持し、それをテンプレートに渡します。

change_list_templateが設定される場合、djangoはそのテンプレートを使用します。それ以外の場合、djangoは標準のdjangoテンプレートを使用します。

def changelist_view (self、request、extra_context = None)が呼び出された場合、djangoはその関数を使用してコンテンツを作成します。それ以外の場合は、デフォルトのdjangoビューを使用します。

次に、admin/myapp/extras/sometemplate_change_form.htmlファイルを作成して{{total}}、任意の場所に配置します。

管理者テンプレートをオーバーライドする方法のガイド そして、ここに管理者ビューをオーバーライドする方法があります

更新:aggregate合計を計算するための簡単なものを追加します。編集して、必要に応じて設定できます。

UPDATE 2:ModelAdminテンプレートオーバーライドオプションがからModelAdmin.change_form_templateに修正されましたModelAdmin.change_list_template。(ありがとうc4urself)。はい。ただし、デフォルトのdjango adminテンプレートを変更することは、他の多くのModelAdminで使用されており、関連するテンプレートが更新されると問題が発生する可能性があるため、非常に悪い選択です。



注意
フィルターを使用しても合計は変わりません。以下のコメントを参照してください。

于 2012-01-06T13:53:09.217 に答える
37

これを行う Django の方法は、django の管理アプリが使用する ChangeList クラスをオーバーライドすることだと思います。django 1.2 でこれを行うget_changelistには、admin クラスでメソッドを呼び出します。私の例TomatoAdminでは、カスタムChangeList calssを返すこのメソッドを呼び出します。この ChangeList クラス:MyChangeListのコンテキストに追加の属性を追加するだけですchange_list.html

change_list.html が次のディレクトリにあることを確認します。

app_label/change_list.html

例では、これは次のとおりです: templates/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 %}

これをあなたが望むようにスタイルする方法はあなたに任せます。

于 2012-01-05T15:27:25.870 に答える
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)

次に、その行のテンプレートが必要ですmyapp/totals_row.html(テンプレートがある場所に関係なく):

<table id="result_totals">
    <tfoot>
        <tr>
            {% for total in totals_row %}<td>{{ total }}</td>{% endfor %}
        </tr>
    </tfoot>
</table>

次に、次のように、Django のデフォルトから継承するカスタム管理テンプレートにそれを配線する必要があります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 管理テンプレートのかなり危険なコピー アンド ペーストが必要になるためです。おまけとして、次の 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>

1 つの注意点: これはすべて、存在するすべてのアイテムではなく、現在表示されているアイテムの合計のみを反映します。これを回避する1つの方法は、潜在的なパフォーマンスへの影響を気にしない場合、クラスにlist_per_page実行不可能なほど大きな数を設定することです。ModelAdmin

于 2012-01-05T15:04:56.973 に答える
0

管理ビューをオーバーライドするカスタム ビューを作成すると、現在のページ情報とともにクエリセットを取得し、データをスライスして現在のページに適した合計を作成できるはずです。真の合計が必要な場合は、探しているオプションとしてカスタムの上書きされた管理ビューがまだ表示されます。

于 2011-12-18T03:09:04.330 に答える
-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)
于 2011-12-17T02:31:43.850 に答える