python django django-admin django-views django-1.2

python - django-admin: Añadir fila extra con totales



django-views django-1.2 (7)

AFAIK no hay manera de hacer esto sin crear una vista personalizada. El concepto es un poco defectuoso de todos modos, porque un usuario esperaría que tal fila muestre el total solo para los objetos visibles, en lugar de todos los objetos en el conjunto de consultas. Por lo tanto, cualquier paginación daría lugar a confusión.

Además, puede agregar columnas adicionales a una vista de lista de administradores haciendo algo como lo siguiente:

class ItemAdmin(admin.ModelAdmin): model = Item list_display = (''field1'', ''field2'', ''extra_field'') def extra_field(self, obj): return u''%s'' % do_something_with(obj)

Estoy usando el módulo de administración estándar de django para mostrar una lista de filas. Una de las columnas es un campo numérico. Me gustaría mostrar una fila de ''totales'' extra que tenga la mayoría de las columnas en blanco, a excepción de la columna numérica, que debe ser el total de todos los objetos.

¿Hay una forma sencilla de hacer esto dentro del módulo de administración, o estoy mejor haciendo una vista personalizada para él?

Estoy usando Django 1.2.


Creo que la forma en que Django hace esto es anular la clase ChangeList que usa la aplicación de administración de django. Haces esto en django 1.2 llamando al método get_changelist en tu clase de administrador. En mi ejemplo: TomatoAdmin llama a este método devolviendo un calss de ChangeList personalizado. Esta clase de ChangeList: MyChangeList simplemente agrega un atributo adicional al contexto de change_list.html .

Asegúrese de que change_list.html esté en el siguiente directorio:

app_label/change_list.html

en el ejemplo, esto es: templates / admin / tomato / change_list.html

models.py (Un modelo simple con un campo entero)

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

admin.py (su clase de administrador y una clase personalizada de 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 (solo bit relevante, copiar / pegar el existente y extenderlo)

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

Te lo dejaré a ti como estilizar esto de la manera que lo quieras.


Este hilo continúa durante un tiempo, pero probablemente no sea el último que esté buscando esa característica. Por lo tanto, creé un paquete que facilita la suma de totales.

Checkout https://github.com/douwevandermeij/admin-totals

Uso:

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

Siéntete libre de bifurcarlo y mejorarlo.


Ok, entonces hay una manera de hacerlo, involucrando agregar un par de etiquetas de plantillas nuevas y extender las plantillas de administración.

En primer lugar, en la carpeta de templatetags la aplicación, crea un archivo admin_totals.py que contiene una etiqueta de plantilla para crear una fila de totales:

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)

Luego necesitas la plantilla para dicha fila en myapp/totals_row.html (donde sea que estén tus plantillas):

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

Luego, debe conectar eso a una plantilla de administración personalizada myapp/mymodel_admin.html del valor predeterminado de Django, como myapp/mymodel_admin.html :

{% extends "admin/change_list.html" %} {% load admin_totals %} {% block result_list %} {{ block.super }} {% totals_row cl %} {% endblock %}

Finalmente, lo admin.py a la configuración en tu archivo admin.py en tu aplicación:

class MyModelAdmin(ModelAdmin): list_display = (''name'', ''date'', ''numerical_awesomeness'') total_functions = {''numerical_awesomeness'': sum} change_list_template = ''myapp/mymodel_admin.html''

Eso debería conectarse en la plantilla de administración personalizada para su nuevo modelo, mostrando la fila de totales. También puede ampliarlo con otras funciones de resumen distintas de la sum , si así lo desea.

Un pequeño punto a la izquierda: la fila de totales no está realmente en la tabla de resultados, porque eso requeriría copiar y pegar de forma bastante retorcida las plantillas de administración de Django. Para obtener puntos de bonificación, puede agregar el siguiente fragmento de JavaScript en la parte inferior de su archivo totals_row.html :

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

Una advertencia: todo esto solo reflejará los totales de los elementos mostrados actualmente, en lugar de todos los elementos existentes. Una forma de evitar esto es establecer list_per_page en un número ModelAdmin grande en su clase ModelAdmin , si no le importa el posible impacto en el rendimiento.


Sí, puedes hacerlo de muchas maneras, pero la mayoría de las formas de hacerlo de django es:

Primero anule la vista predeterminada de la lista de django ... y proporcione un nuevo directorio de archivos de plantilla

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

Me gusta:

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)

Entonces, agrega el contexto de su vista de lista a un "total" que mantiene su valor total y lo pasa a la plantilla.

si se establecerá change_list_template , django usa esa plantilla, de lo contrario, usa la plantilla estándar de django.

Si se llama def changelist_view (self, request, extra_context = None) , django usa esa función para crear el contenido; de lo contrario, usa las vistas django predeterminadas.

Luego cree un admin/myapp/extras/sometemplate_change_form.html y coloque su {{total}} en el lugar que desee.

Una guía sobre cómo anular las plantillas de administración Y aquí es cómo anular las vistas de administración

ACTUALIZACIÓN: agrego un aggregate simple para calcular el total. Puedes editarlo para configurarlo como tus necesidades.

ACTUALIZACIÓN 2 : La opción de anulación de la plantilla ModelAdmin se corrigió de ModelAdmin.change_form_template a ModelAdmin.change_list_template . (gracias c4urself). Sí, pero cambiar la plantilla de administración de django predeterminada es una opción realmente mala, ya que es utilizada por muchos otros ModelAdmin y puede causar problemas si se actualizan las plantillas relacionadas.



NB :
El Total no cambia cuando se usan filtros, vea el comentario a continuación.


Si crea una vista personalizada sobre la vista de administrador, debería poder tomar el conjunto de consultas junto con la información de la página actual y dividir los datos para crear un total apropiado para la página actual. Si desea un total verdadero, aún veo una vista de administrador anulada como la opción que está buscando.


También está el paquete "django-admin-changelist-stats" que puede proporcionar estadísticas de resumen. Lo he utilizado con éxito en un proyecto Django 1.6.

IMO usa la solución de c4urself para la personalización de plantillas de grano fino, pero si sus únicos agregados (suma / promedio / mínimo / máximo) de tablas están buscando, entonces esta solución es bastante buena.

Desde su página web.

"Esta sencilla aplicación proporciona estadísticas y capacidades de agregación para la vista de la lista de cambios del administrador de Django. Permite mostrar las estadísticas al final de la página de la lista de cambios de una manera sencilla, simplemente agregando una opción al objeto de administrador modelo".

Más información, incluidos ejemplos, en su página web del repositorio de bitbucket https://bitbucket.org/frankban/django-admin-changelist-stats/src