#export_excel.py 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 ----------------------------------------------------------------------------------------------------------------- #actions.py from openpyxl import Workbook from django.core.exceptions import PermissionDenied from django.http import HttpResponse from datetime import datetime, date from action_export.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): if not request.user.is_staff: raise PermissionDenied opts = self.model._meta field_names = self.list_display file_name = unidecode(opts.verbose_name) blank_line = [] 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 = "Export as excel" ---------------------------------------------------------------------------------------------------------------- In admin just do: from actions import export_as_xls class SomeAdmin(admin.ModelAdmin): . . . actions = [export_as_xls]