Я хочу создать новое приложение «Бизнес», используя структуру Django. Любые предложения относительно того, что я могу использовать в качестве структуры отчетности? Приложение должно будет генерировать отчеты по различным бизнес-сущностям, включая сводки, итоги, группировку и т. д. По сути, существует ли аналог отчетов Crystal для Django/Python?
Параметры отчетов Django
Ответы (5)
На djangopackages.com есть сетка, которая может быть полезна для оценки параметров:
https://www.djangopackages.com/grids/g/reporting/
Я сделал django-report-builder. Он позволяет создавать запросы ORM с помощью графического интерфейса и создавать отчеты в виде электронных таблиц. Он не может создавать шаблоны, хотя было бы неплохо добавить эту функцию.
Это просто шаблоны HTML с обычными функциями просмотра.
Это не требует многого: параметры поступают из формы; напишите запрос в функции просмотра, передав набор запросов в шаблон. Шаблон представляет отчет.
Зачем вам нужно что-то большее, чем это?
Вы можете использовать общий список/детальные представления чтобы избавить себя от необходимости писать столько кода. Если вы идете по этому пути, вы предоставляете набор запросов и шаблон общему представлению, которое выполняет часть обработки за вас.
Поскольку вы должны написать запрос в отчетах Crystal или Django, вы не получите много преимуществ от инструмента «отчетности».
Основываясь на предложении @s-lott, вы можете добавлять отчеты на сайт администратора, используя прокси-модель, класс администратора модели с пользовательским changelist_view()
и настраиваемым шаблоном, производным от admin/base_site.html
.
Предполагая, что Django v2.1 (для разрешений на просмотр модели) и классический домен клиентов, продуктов и продаж, вот полный пример:
- Создайте прокси-модель для отображения отчета на странице индекса администратора:
class SalesReport(SalesOrder): class Meta: proxy = True
- Создайте класс администратора модели для модели:
@admin.register(SalesReport) class SalesReportAdmin(admin.ModelAdmin): ...
- Реализовать представление отчета:
def sales_report(self, request): monthly_products_by_customer_sql = ''' SELECT c.name AS customer, p.name AS product, COUNT(DISTINCT o.id) AS total_orders, SUM(oi.quantity) AS total_products, SUM(oi.quantity * oi.price) AS total_amount FROM sales_salesorder o INNER JOIN customers_customer c ON o.customer_id = c.id INNER JOIN sales_salesorderitem oi ON o.id = oi.sales_order_id INNER JOIN products_product p ON oi.product_id = p.id WHERE o.departure_date >= %s AND o.departure_date <= %s GROUP BY c.id, p.id ORDER BY total_amount DESC; ''' start, end = get_previous_month_start_end_date() with connection.cursor() as cursor: cursor.execute(monthly_products_by_customer_sql, (start, end)) results = namedtuplefetchall(cursor) totals = Totals( total_orders=sum(r.total_orders for r in results), total_products=sum(r.total_products for r in results), total_amount=sum(r.total_amount for r in results), ) context = dict( self.admin_site.each_context(request), title=f'Sales report for {start} - {end}', period_start=start, period_end=end, results=results, totals=totals, ) return TemplateResponse(request, 'sales/report.html', context)
- Вернуть представление отчета из
changelist_view()
, завернув его вadmin_site.admin_view()
для защиты от несанкционированного доступаdef changelist_view(self, request): return self.admin_site.admin_view(self.sales_report)(request)
Удалите разрешения на добавление, изменение и удаление, чтобы осталось только разрешение на просмотр, и защитите представления изменений и истории:
def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False def change_view(self, *args, **kwargs): raise PermissionDenied def history_view(self, *args, **kwargs): raise PermissionDenied
Помощники и импорт для представления
sales_report()
:from collections import namedtuple from django.core.exceptions import PermissionDenied from django.db import connection from django.template.response import TemplateResponse Totals = namedtuple('Totals', ['total_orders', 'total_products', 'total_amount']) def namedtuplefetchall(cursor): '''Return all rows from a cursor as a namedtuple''' desc = cursor.description nt_result = namedtuple('Result', [col[0] for col in desc]) return [nt_result(*row) for row in cursor.fetchall()] def get_previous_month_start_end_date(): today = datetime.date.today() prev_month_last = datetime.date(today.year, today.month, 1) - datetime.timedelta(1) prev_month_first = datetime.date(prev_month_last.year, prev_month_last.month, 1) return prev_month_first, prev_month_last
- Добавьте следующий шаблон в
sales/report.html
, производный отadmin/base_site.html
, чтобы использовать макет администратора:{% extends "admin/base_site.html" %} {% block content %} <div id="content-main"><div class="results"> <table> <thead> <tr> <th scope="col"><div class="text">Customer</div></th> <th scope="col"><div class="text">Product</div></th> <th scope="col"><div class="text"># orders</div></th> <th scope="col"><div class="text"># products</div></th> <th scope="col"><div class="text">Amount €</div></th> </tr> </thead> <tbody> {% for result in results %} <tr class="row1"> <td>{{ result.customer }}</td> <td>{{ result.product }}</td> <td>{{ result.total_orders }}</td> <td>{{ result.total_products }}</td> <td>{{ result.total_amount|floatformat:2 }}</td> </tr> {% endfor %} <tr class="row1" style="font-weight: bold"> <td> </td><td> </td> <td>{{ totals.total_orders }}</td> <td>{{ totals.total_products }}</td> <td>{{ totals.total_amount|floatformat:2 }}</td> </tr> </tbody> </table> </div></div> {% endblock %}
Теперь отчет будет отображаться на индексной странице администратора со значком только для просмотра ????, он защищен от несанкционированного доступа и имеет единый вид с остальной частью сайта администратора.
Изменить Похоже, что оба пакета исчезли, но теперь у нас есть хорошая структура данных, заимствованная из R -- DataFrame в пакете pandas Краткий туториал (обратите внимание на раздел "Группировка")
Я не знаю о полном решении для создания отчетов для Django (или Python), но создавать отчеты с помощью Django довольно просто с ORM или без него:
- django-tables может дать вам очень простую структуру для обработки данных таблицы (сортировка на стороне сервера по возрастанию/убыванию и т.д.)
- вы можете использовать стандартные агрегаты набора запросов django 1.1 (их использует django-reporting) для итоговых/промежуточных итогов.
Лично я использую django-tables и пакет python datashaping для быстрой сводки/avg/median/IQR/ материал для фильтрации, потому что у меня есть много разных источников данных (данные REST, две базы данных mysql, файлы csv из R), и лишь немногие из них сейчас находятся в базе данных django.
Pycha — один из кандидатов для рисования простых диаграмм.
Мне не нравятся сетки на основе ajax на стороне клиента и т. д. для отчетов, но вы также можете использовать его с шаблонами django.
django tables
и datashaping
больше не существуют - все репозитории и страницы документов дают 404s
- person lsh; 10.05.2014