Skip to content

Instantly share code, notes, and snippets.

@kelwys
Last active June 10, 2024 07:31
Show Gist options
  • Save kelwys/44f1503c45d20af14faffd88a335912f to your computer and use it in GitHub Desktop.
Save kelwys/44f1503c45d20af14faffd88a335912f to your computer and use it in GitHub Desktop.
Export Django Admin to Excel with Action
from openpyxl import Workbook
from django.http import HttpResponse
from datetime import datetime, date
from .export_excel import ExportExcelAction
from openpyxl.styles import Font
from unidecode import unidecode
def style_output_file(file):
black_font = Font(color='000000', bold=True)
for cell in file["1:1"]:
cell.font = black_font
for column_cells in file.columns:
length = max(len((cell.value)) for cell in column_cells)
length += 10
file.column_dimensions[column_cells[0].column_letter].width = length
return file
def convert_data_date(value):
return value.strftime('%d/%m/%Y')
def convert_boolean_field(value):
if value:
return 'Yes'
return 'No'
def export_as_xls(self, request, queryset):
opts = self.model._meta
field_names = self.list_display
file_name = unidecode(opts.verbose_name)
wb = Workbook()
ws = wb.active
ws.append(ExportExcelAction.generate_header(self, self.model, field_names))
for obj in queryset:
row = []
for field in field_names:
is_admin_field = hasattr(self, field)
if is_admin_field:
value = getattr(self, field)(obj)
else:
value = getattr(obj, field)
if isinstance(value, datetime) or isinstance(value, date):
value = convert_data_date(value)
elif isinstance(value, bool):
value = convert_boolean_field(value)
row.append(str(value))
ws.append(row)
ws = style_output_file(ws)
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = f'attachment; filename={file_name}.xlsx'
wb.save(response)
return response
export_as_xls.short_description = "Exportar para excel"
from actions import export_as_xls
class SomeAdmin(admin.ModelAdmin):
.
.
.
actions = [export_as_xls]
class ExportExcelAction:
@classmethod
def generate_header(cls, admin, model, list_display):
def default_format(value):
return value.replace('_', ' ').upper()
header = []
for field_display in list_display:
is_model_field = field_display in [f.name for f in model._meta.fields]
is_admin_field = hasattr(admin, field_display)
if is_model_field:
field = model._meta.get_field(field_display)
field_name = getattr(field, 'verbose_name', field_display)
header.append(default_format(field_name))
elif is_admin_field:
field = getattr(admin, field_display)
field_name = getattr(field, 'short_description', default_format(field_display))
header.append(default_format(field_name))
else:
header.append(default_format(field_display))
return header
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment