Обработка данных с использованием цикла for, python django

Я пытаюсь понять, как правильно составить цикл, выбрать данные, чтобы получить желаемый результат. Я создаю excel файл с помощью openpyxl. В своем цикле я прохожу по объектам и последовательно записываю их в свой файл, но мне нужно группировать объекты по их же атрибуту "Филиалу".

В excel у меня сейчас выгружается таблица в следующем виде:

В excel у меня сейчас выгружается таблица в следующем виде:

Я же хочу получить следующий результат:

Я же хочу получить следующий результат:

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

models.py

class Filial(models.Model):
    """
    Модель-справочник: Филиалы
    """
    id_filial = models.AutoField(primary_key=True, verbose_name='Идентификатор филиала')
    name_filial = models.CharField(max_length=256, verbose_name='Наименование филиала')

    def __str__(self):
        return self.name_filial

    class Meta:
        db_table = 'Filial'
        verbose_name = 'Филиал'
        verbose_name_plural = 'Филиалы'

class Group(models.Model):
    """
    Модель: Группы работ
    """
    id_group = models.AutoField(primary_key=True, verbose_name='Идентификатор группы работ')

    id_filial = models.ForeignKey('Filial', models.DO_NOTHING, related_name='filial',
                                  verbose_name='Филиал')

    id_cs = GroupedForeignKey(Station, "id_filial", on_delete=models.SET_NULL, null=True, related_name='cs')

    id_gpu = GroupedForeignKey(GPU, "id_cs", on_delete=models.SET_NULL, blank=True, null=True, related_name='gpu', verbose_name='Оборудование')

    name_group = models.CharField(max_length=256, verbose_name='Наименование группы работ')
    short_description = models.CharField(max_length=256)

    def __str__(self):
        return self.name_group

    class Meta:
        db_table = 'Group'
        verbose_name = 'Группа работ'
        verbose_name_plural = 'Группы работ'

views.py

class Start(CreateView):
    template_name = 'main/start.html'

    def get(self, request, *args, **kwargs):
        group = Group.objects.all()
        groups = group.order_by('creation_date')

        """
        Выгрузка листа
        """
        if request.GET.get('_export') == 'openpyxl':
            return self.download_report_openpyxl(request, groups)

        context = {
            'groups': groups,
        }
        return render(request, self.template_name, context)

    def download_report_openpyxl(self, request, groups=None, *args, **kwargs):
        data = report_xlsx_openpyxl(groups, )
        # PART UPDATED TO SHOW DOWNLOAD REPORT DIALOG
        bio = io.BytesIO()
        data.save(bio)  # save to memory stream
        bio.seek(0)  # rewind the stream
        response = HttpResponse(
            bio.getvalue(),  # use the stream's contents
            content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        )

        response["Content-Disposition"] = 'attachment; filename = "report.xlsx"'
        response["Content-Encoding"] = "UTF-8"
        return response

report.py

def report_xlsx_openpyxl(groups=None, ):
    """
    Создание .xlsx файла и запись в него
    """
    wb = Workbook()
    ws = wb.active
    ws.title = "Список работ"

    # Заполнение столбцов данными
    for group in groups:
        works = Works.objects.filter(id_group=group.id_group)
        output = {'full_descriptions': Works.objects.filter(id_group=group.id_group).values_list('full_description',                                                                                  flat=True).last(),
}

        data = (
                    [str(group.id_gpu),                    # Наименование оборудования
                     str(group.name_group),                # Наименование работ
                     str(group.start_date),                # Начало работ
                     str(group.end_date),                  # Окончание работ
                     str(output['full_descriptions']),     # Примечание
                     str(group.id_filial),                 # Филиал
                     str(group.id_group),                  # Идентификатор группы работ
                     ],
                )

        for row in data:
            ws.append(row)

    wb.save('test.xlsx')
    return wb

Для достижения цели было необходимо:

1) Отсортировать QuerySet:

groups = group.order_by('id_filial__name_filial', 'id_cs__name_cs', 'id_gpu__name_gpu')

2) Формируем отчет в .xlsx файле:

cs1 = None

# Заполнение столбцов данными
for group in groups:
    cs2 = str(group.id_cs)
    if cs1 == cs2:
        pass
    else:
        cs_name = [cs2]
        ws.append(cs_name)                       # Вставляем строку
        rows = str(ws.max_row)                   # Вычисляем количество строк
        ws.merge_cells('A' + rows + ':O' + rows) # Объединяем ячейки
        cs1 = cs2

    data = [
             ...
    ]
    ws.append(data)
Вернуться на верх