Python(Django)页面导出Excel

Python(Django)页面导出Excel表格数据

最近做项目要使用到 导出Excel 的表格,正好有 openpyxl 这个库。

今天给大家分享一下如何使用这个库并在 Django 页面导出Excel表;

首先,安装openpyxl库:

pip install openpyxl

现在,我们可以写我们的代码了。

案例:我们以导出病人到医院的挂号信息为例来讲解 openpyxl 的使用;

导入需要用到的库

首先,在自己的视图函数中导入模块,需要使用到如下的三个模块:

from openpyxl import Workbook	# 操作Excel的库
from io import BytesIO		# 实现了在内存中读写bytes
from django.utils.http import urlquote		# 解决导出Excel文件无法使用中文文件名

openpyxl 库是用来用Python代码操作Excel表的库;

BytesIO 可以实现在内存中读写bytes;

urlquote 该方法为了解决导出Excel文件因无法使用中文文件名的问题;

BytesIO

StringIO 操作的只能是 str ,如果要操作二进制数据,就需要使用 BytesIO

BytesIO 实现了在内存中读写 bytes ,我们创建一个 BytesIO ,然后写入一些 bytes :

>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'

请注意,写入的不是 str,而是经过 UTF-8 编码的 bytes;

和 StringIO 类似,可以用一个 bytes 初始化 BytesIO ,然后,像读文件一样读取:

>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'

小结

StringIO 和 BytesIO 是在内存中操作 str 和 bytes 的方法, 使得和读写文件具有一致的接口。

定义导出函数export_excel

def export_excel(request):
    import datetime
    from django.http import HttpResponse
	from openpyxl import Workbook
    from io import BytesIO
    from django.utils.http import urlquote
    wb = Workbook()		# 生成一个工作簿(即一个Excel文件)
    wb.encoding = 'utf-8'
    sheet1 = wb.active	# 获取第一个工作表(sheet1)
    sheet1.title = '挂号信息'	# 给工作表1设置标题
    row_one = ['门诊编号', '主治医生', '挂号时间', '挂号科室', '状态',
               '姓名', '身份证号', '挂号费', '社保号', '联系电话', '是否自费',
               '性别', '年龄', '职业', '初复诊', '备注']
    for i in range(1, len(row_one)+1):	# 从第一行开始写,因为Excel文件的行号是从1开始,列号也是从1开始
        # 从row=1,column=1开始写,即将row_one的数据依次写入第一行
        sheet1.cell(row=1, column=i).value=row_one[i-1]
   	all_obj = Registration.objects.all()
    for obj in all_obj:
        max_row = sheet1.max_row + 1	# 获取到工作表的最大行数并加1
        obj_info = [obj.id,obj.doctor.real_name,obj.regist_date,obj.department.department_name,
                	obj.status,obj.name,obj.id_number,obj.cost,obj.social_num,
                    obj.phone, obj.is_paying, obj.sex, obj.age, obj.occupation, 
                    obj.is_first, obj.remark]
       	for x in range(1, len(obj_info)+1):		# 将每一个对象的所有字段的信息写入一行内
            sheet.cell(row=max_row, column=x).value = obj_info[x-1]
    # 准备写入到IO中
    output = BytesIO()
   	wb.save(output)	 # 将Excel文件内容保存到IO中
    output.seek(0)	 # 重新定位到开始
    # 设置HttpResponse的类型
    response = HttpResponse(output.getvalue(), content_type='application/vnd.ms-excel')
    ctime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    file_name = '挂号信息%s.xls' % ctime	# 给文件名中添加日期时间
    file_name = urlquote(file_name)	 # 使用urlquote()方法解决中文无法使用的问题
    response['Content-Disposition'] = 'attachment; filename=%s' % file_name
    # response.write(output.getvalue())	 # 在设置HttpResponse的类型时,如果给了值,可以不写这句
    return response

补充一下我们的 model :

注意:我们的模型里有两个关联的字段:department、doctor;

class Registration(models.Model):
    """
    患者挂号信息
    """
    name = models.CharField(max_length=20, verbose_name='患者姓名')
    id_number = models.CharField(max_length=18, verbose_name='患者身份证')
    cost = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='挂号费')
    social_num = models.CharField(max_length=10, null=True, verbose_name='社保号')
    phone = models.CharField(max_length=11, verbose_name='联系电话')
    is_paying = models.BooleanField(default=True, verbose_name='是否自费')
    sex = models.BooleanField(default=1, verbose_name='性别')
    age = models.PositiveSmallIntegerField(null=True, verbose_name='年龄')
    occupation = models.CharField(max_length=20, null=True, verbose_name='职业')
    is_first = models.BooleanField(default=1, verbose_name='是否是初诊')
    regist_date = models.DateTimeField(auto_now_add=True, verbose_name='挂号时间')
    status_choice = ((1, '已住院'), (2, '已出院'), (3, '已结算'), (4, '未结算'), (5, '已挂号'), (6, '已退号'))
    status = models.PositiveSmallIntegerField(choices=status_choice, verbose_name='患者挂号状态')
    department = models.ForeignKey(Department, related_name='registration', on_delete=models.DO_NOTHING, verbose_name='关联科室')
    doctor = models.ForeignKey(DoctorManage, related_name='registration', on_delete=models.DO_NOTHING, verbose_name='关联医生')
    remark = models.CharField(max_length=100, null=True, verbose_name='备注')

效果

请求我们的视图URL时,会看到:

Python(Django)页面导出Excel

现在,我们的导出Excel文件功能已初步完成!

本文学习自:在Django中,导出Excel表格,通过使用自己的方法完成!