Обработка данных с использованием цикла for, python django
Я пытаюсь понять, как правильно составить цикл, выбрать данные, чтобы получить желаемый результат. Я создаю excel файл с помощью openpyxl. В своем цикле я прохожу по объектам и последовательно записываю их в свой файл, но мне нужно группировать объекты по их же атрибуту "Филиалу".
В 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)