2011-12-17 38 views
28

Tôi đang sử dụng mô-đun quản trị django chuẩn để hiển thị danh sách các hàng. Một trong các cột là một trường số. Tôi muốn hiển thị một hàng 'tổng cộng' bổ sung có hầu hết các cột là trống, ngoại trừ cột số, mà nên là tổng số cho tất cả các đối tượng.django-admin: Thêm hàng bổ sung với tổng số

Có cách nào đơn giản để thực hiện việc này trong mô-đun quản trị hay không, tôi có nên bật chế độ xem tùy chỉnh cho mô-đun đó không?

Tôi đang sử dụng Django 1.2.

+0

Chỉ cần đảm bảo: Bạn có nghĩa là tổng số tiền cho tất cả các đối tượng _on trang hiện tại hay _all các đối tượng trong cơ sở dữ liệu_? –

+0

@ lazerscience: ý tôi là đối tượng hiện đang hiển thị (vì vậy nếu bạn áp dụng bộ lọc nó sẽ chỉ hiển thị các mục đã lọc) – Claudiu

Trả lời

-3

AFAIK không có cách nào để thực hiện việc này mà không tạo chế độ xem tùy chỉnh. Tuy nhiên, khái niệm này có một chút thiếu sót, bởi vì người dùng mong đợi một hàng như vậy để hiển thị tổng số chỉ cho các đối tượng hiển thị, thay vì tất cả các đối tượng trong bộ truy vấn. Do đó, bất kỳ sự phân trang nào cũng dẫn đến sự nhầm lẫn.

Là một sang một bên, bạn có thể bổ sung thêm cột đến một cái nhìn danh sách quản trị bằng cách làm một cái gì đó như sau:

class ItemAdmin(admin.ModelAdmin): 
    model = Item 

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

    def extra_field(self, obj): 
     return u'%s' % do_something_with(obj) 
0

nếu bạn tạo một giao diện tùy chỉnh overiding quan điểm quản trị bạn sẽ có thể để mất queryset cùng với thông tin trang hiện tại và cắt dữ liệu để tạo tổng số thích hợp cho trang hiện tại. nếu bạn muốn có tổng số thực sự hơn tôi vẫn thấy chế độ xem quản trị viên được ghi đè tùy chỉnh làm tùy chọn bạn đang tìm kiếm.

6

Ok, do đó, có một cách để làm điều này, liên quan đến việc thêm vào một vài thẻ mẫu mới và mở rộng mẫu quản trị viên.

Trước hết, trong thư mục của ứng dụng của bạn templatetags, bạn tạo một tập tin admin_totals.py chứa một mẫu thẻ để tạo ra một hàng tổng:

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) 

Sau đó, bạn cần mẫu cho hàng nói trong myapp/totals_row.html (bất cứ nơi nào các mẫu của bạn là):

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

Sau đó, bạn cần để dây đó vào một mẫu tùy chỉnh quản trị kế thừa từ mặc định của Django, chẳng hạn như myapp/mymodel_admin.html:

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

{% load admin_totals %} 

{% block result_list %} 
{{ block.super }} 
{% totals_row cl %} 
{% endblock %} 

Cuối cùng, bạn dây đó vào cấu hình trong tập tin admin.py bạn trong ứng dụng của bạn:

class MyModelAdmin(ModelAdmin): 

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

    change_list_template = 'myapp/mymodel_admin.html' 

Đó nên dây trong tùy chỉnh mẫu quản trị cho mô hình mới của bạn, hiển thị dòng tổng số. Bạn cũng có thể mở rộng nó với các chức năng tóm tắt khác ngoài sum, nếu bạn muốn.

Một điểm nhỏ còn lại: hàng tổng cộng không thực sự nằm trong bảng kết quả, vì điều đó sẽ yêu cầu sao chép và dán các mẫu quản trị Django khá gnarly. Đối với điểm thưởng, bạn có thể thêm vào smidge sau của hoạt Javascript để dưới cùng của totals_row.html tập tin của bạn:

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

Một caveat: tất cả điều này sẽ chỉ phản ánh tổng cho các mục đang hiển thị, chứ không phải cho tất cả các mục trong sự tồn tại. Một cách chung quanh việc này là đặt list_per_page thành một số lớn bất thường trên lớp ModelAdmin của bạn, nếu bạn không nhớ đến lần truy cập hiệu suất tiềm năng.

25

Tôi nghĩ cách Django để làm điều này là ghi đè lên lớp ChangeList mà ứng dụng quản trị của django sử dụng. Bạn làm điều này trong django 1.2 bằng cách gọi phương thức get_changelist trong lớp quản trị của bạn. Trong ví dụ của tôi: TomatoAdmin gọi phương thức này trả về một calss ChangeList tùy chỉnh. Lớp ChangeList này: MyChangeList chỉ cần thêm thuộc tính bổ sung vào ngữ cảnh change_list.html.

Hãy chắc chắn rằng change_list.html là trong thư mục sau:

app_label/change_list.html 

trong ví dụ này là: templates/admin/cà chua/change_list.html

models.py (một mô hình đơn giản với một trường số nguyên)

class CherryTomato(models.Model): 
    name = models.CharField(max_length=100) 
    num_in_box = models.IntegerField() 

admin.py (lớp quản trị của bạn và một lớp tùy chỉnh danh sách thay đổi)

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 (bit chỉ có liên quan, sao chép/dán một hiện có và mở rộng nó)

{% 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 %} 

tôi sẽ để nó cho bạn cách tạo kiểu theo cách bạn muốn.

+0

Thực ra đây là giải pháp tốt hơn, bởi vì tùy biến Danh sách thay đổi như trên có thể tổng hợp "tổng" đối với các bộ lọc đã chọn. – pista329

+0

Tốt hơn và có thể làm quen với các bộ lọc :) – elsadek

+0

Điều này gần hoàn hảo đối với tôi. Tổng số là phản ánh phân trang cũng như kể từ đó đi vào bộ truy vấn. – teewuane

28

Vâng, bạn có thể làm điều đó bằng nhiều cách, nhưng hầu hết django-ist cách làm là:

Đầu ghi đè django mặc định xem danh sách ... Và cung cấp cho một thư mục tập tin mẫu mới

ModelAdmin.changelist_view(self, request, extra_context=None) 

Giống như:

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) 

Vì vậy, bạn thêm bối cảnh xem danh sách của bạn một 'tổng' mà giữ tổng giá trị của mình và vượt qua nó cho mẫu.

nếu change_list_template sẽ đặt, django sử dụng mẫu đó, nếu không, nó sẽ sử dụng mẫu django chuẩn.

Nếu def changelist_view (tự, yêu cầu, extra_context = Không) được gọi, django sử dụng chức năng đó để tạo nội dung, nếu không nó sẽ sử dụng chế độ xem django mặc định.

Sau đó, tạo tệp admin/myapp/extras/sometemplate_change_form.html và đặt {{total}} của bạn vào bất kỳ địa điểm nào bạn muốn.

Hướng dẫn làm thế nào để override admin templates Và đây là làm thế nào để override admin views

UPDATE: tôi thêm một đơn giản aggregate để tính tổng. bạn có thể chỉnh sửa nó để đặt nó theo nhu cầu của bạn.

CẬP NHẬT 2: Tùy chọn ghi đè mẫu ModelAdmin được sửa từ ModelAdmin.change_form_template thành ModelAdmin.change_list_template. (cảm ơn c4urself).Có, nhưng thay đổi mặc định mẫu admin django là một lựa chọn thực sự xấu, vì nó được sử dụng bởi nhiều ModelAdmin khác và nó có thể gây ra vấn đề nếu các mẫu liên quan được cập nhật.



NB:
Các Tổng số không thay đổi khi sử dụng bộ lọc, xem bình luận dưới đây.

+2

Tôi nghĩ rằng đây là một cách tuyệt vời để đi, tôi tin rằng 'change_form_template' nên là' change_list_template'. Mặc dù bạn không cần phải cung cấp cho nó một tên mẫu nếu bạn ghi đè lên các mẫu quản trị viên. – c4urself

+3

Ngọt, đây thực sự là công thức sao chép-dán mà tôi đang tìm kiếm. Tôi chỉ nói, thay vì cấu hình 'change_list_template' trên lớp Admin, tôi chỉ cần tạo một tệp như:' templates/admin/my_app/my_model/change_list.html', sau đó trong tệp đó chỉ cần sử dụng '{% extends ' admin/change_list.html '%} 'và chỉ ghi đè một khối đơn, như:' {% block result_list%} {{block.super}}

Tổng số là: {{total}} !!!

{% endblock%} '. Thông qua cấu hình;) –

+0

thậm chí sử dụng 'siêu (MyModelAdmin, self) .get_queryset (yêu cầu)', queryset không được cập nhật khi sử dụng bộ lọc, 'Total' luôn dành cho danh sách chưa được lọc, đây không phải là trường hợp Câu trả lời của c4urself mà tôi nghĩ là tốt hơn và sạch hơn. – elsadek

4

Ngoài ra còn có gói "django-admin-changelist-stats" có thể cung cấp số liệu thống kê tóm tắt. Tôi đã sử dụng thành công nó trong một dự án Django 1.6.

IMO sử dụng giải pháp c4urself để tùy chỉnh mẫu chi tiết, nhưng nếu chỉ tổng hợp (sum/avg/min/max) của bảng bạn mới thì giải pháp này khá tốt.

Từ trang web của mình

" ứng dụng đơn giản này cung cấp số liệu thống kê và khả năng kết hợp với quan điểm quản trị danh sách thay đổi Django. Nó cho phép để hiển thị số liệu thống kê ở phần cuối của trang sách thay đổi một cách dễ dàng, chỉ cần thêm một lựa chọn đến đối tượng mô hình quản trị. "

biết thêm thông tin, bao gồm các ví dụ, tại bitbucket kho trang web của nó https://bitbucket.org/frankban/django-admin-changelist-stats/src

+0

tiếc là thư viện này không hỗ trợ tổng hợp trên các trường có liên quan - ví dụ: Tổng ('menu__meal__cost') không thành công – d3vid

2

chủ đề này đang xảy ra trong một thời gian , nhưng có lẽ tôi không phải là người cuối cùng đang tìm kiếm một tính năng như vậy. Do đó, tôi đã tạo một gói giúp dễ dàng thêm tổng số.

Thanh toán https://github.com/douwevandermeij/admin-totals

Cách sử dụng:

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

Hãy đến ngã ba nó và cải thiện nó.

Các vấn đề liên quan