Создание списков/отчетов со встроенными сводками в Django

Я пытаюсь написать представление, которое будет генерировать отчет, отображающий все элементы в моей системе инвентаризации, и предоставлять сводки в определенный момент. Между прочим, этот отчет представляет собой всего лишь HTML-шаблон.

В моем случае каждый элемент является частью заказа. В заказе может быть несколько элементов, и я хочу иметь возможность отображать сводки на основе суммы после окончания каждого заказа.

Итак, отчет выглядит примерно так:

Order #25        <Qty> <Qty Sold> <Cost> <Cost Value>
Some Item          2       1       29.99    29.99
Another Item       4       0       10.00    40.00
<Subtotal Line>    6       1       39.99    69.99
Order #26        <Qty> <Qty Sold> <Cost> <Cost Value>
... Etc, you get the point

Теперь я вполне способен отображать все значения и уже имею отчет, показывающий все элементы, но я понятия не имею, как я могу разместить промежуточные итоги в отчете, не выполняя множество запросов. Поля Quantity, Qty Sold и Cost являются лишь частью модели Item, а Cost Value — простой функцией модели.

Любая помощь будет оценена по достоинству. Заранее спасибо :-)


person Bartek    schedule 13.02.2009    source источник


Ответы (3)


Итого: SELECT SUM(qty) GROUP BY order_number вещей.

Они полностью отделены от запроса для получения подробной информации.

Результаты двух запросов необходимо чередовать. Хороший способ сделать это — создать каждый заказ в виде кортежа ( list_of_details, appropriate summary ).

Тогда дисплей легко

{% for order in orderList %}
    {% for line in order.0 %}
        {{ line }}
    {% endfor %}
    {{ order.1 }}
{% endfor %}

Сложная часть — это чередование двух запросов.

details = Line.objects.all()
ddict = defaultdict( list )
for d in details:
    ddict[d.order_number].append(d)

interleaved= []
subtotals = ... Django query to get subtotals ... 
for s in subtotals:
    interleaved.append( ( ddict[s.order], s.totals ) )

Этот interleaved объект можно передать вашему шаблону для рендеринга.

person S.Lott    schedule 13.02.2009
comment
Огромное спасибо! Немного поиграв с Django ORM, чтобы получить правильную функциональность GROUP BY, у меня почти все работает. Спасибо еще раз - person Bartek; 13.02.2009

Вы можете вычислить промежуточные итоги в Python в представлении Django.

Промежуточные итоги могут храниться в экземплярах объекта Model с атрибутом, указывающим, что это промежуточный итог. Чтобы упростить шаблон отчета, вы можете вставить объекты промежуточных итогов в нужные места в списке результатов и использовать атрибут промежуточных итогов для другого отображения строк промежуточных итогов.

person Akbar ibrahim    schedule 13.02.2009
comment
Таким образом, вы говорите, что в основном перебираете созданный набор запросов report через Python, и когда он распознает, что я в новом порядке, я суммирую значения этой группы элементов, а затем ввожу атрибут промежуточного итога в список в нужной точке ? Я надеюсь, что это имеет смысл, это моя лучшая идея на данный момент. - person Bartek; 13.02.2009
comment
Концептуально, да. Фактическая реализация может избежать необходимости обнаруживать новый заказ, используя словарь промежуточных сумм или какую-либо другую реализацию. - person Akbar ibrahim; 13.02.2009

Предполагая, что вы не собираетесь использовать какие-либо поля, специфичные для заказа, вы можете выполнить один запрос к БД, за которым следуют некоторые вычисления python:

from itertools import groupby
items = OrderItem.objects.select_related('order').order_by('order').all() # order_by is essential
items_by_order = dict(groupby(items, lambda x: x.order))
for order, items in items_by_order:
    items_by_order[order]['subtotals'] = ... # calculate subtotals for all needed fields

Это более общий подход по сравнению с использованием отдельного SQL-запроса для вычисления промежуточных итогов, что налагает ответственность за синхронизацию предложений WHERE в обоих запросах. Вы также можете использовать любую агрегатную функцию, а не только те, которые доступны на стороне БД.

person Alexander Lebedev    schedule 13.02.2009