python3 flask-restful xlsxwriter模块导出MYSQL数据库查询结果到EXCEL浏览器下载

需求

开发环境:PYTHON3 + MYSQL + FLASK-SQLALCHEMY
需求:将mysql数据库查询出来的结果直接转为excel并从浏览器直接下载(不保存在服务器)

1、安装模块包:xlswriter

这个包的介绍可以自行百度,我这里后续有时间再补充更新,我们暂时直接切入主题。

首先,安装包:
pip install xlswriter

2、视图类

# order.py
from flask import request, make_response
from flask_restplus import Resource
from itpms.api.v1 import business
......

@api.route('/order/excel/<int:order_id>')
@api.param('order_id', 'order id')
class OrderExcelOperation(Resource):
    """
    订单EXCEL相关API
    """
    @api.doc('Export Order Purchaselist')
    @api.response(return_code.Successful, 'export success')
    def get(self, order_id):
        """导出订单的采购清单"""
        respdata = business.export_purchaselist(order_id)
        resp = make_response(respdata[0])
        resp.headers["Content-Disposition"] = "attachment; filename={}.xlsx".format(respdata[1])
        resp.headers['Content-Type'] = 'application/x-xlsx'
        return resp

3、处理函数

好,上面视图类中引用的就是下面这里的处理函数
数据库模型我就不贴了(使用flask-sqlalchemy生成db对象,然后这里引入使用即可),这个处理函数中的查库以及结果循环你们按你自己的来即可

# business.py
import xlsxwriter
from io import BytesIO
from itpms import db
......


def export_purchaselist(order_id):
    """
    导出订单的采购清单
    :param order_id:
    :return:
    """
    order = Orders.query.get(order_id)
    if not order:
        raise exceptions.MyHttpNotFound('order not found')

    purchaselist = db.session.query(PurchaseList.cicode, PurchaseList.sn, DeviceCategory.name, DeviceCategory.specs,
                                    DeviceCategory.price, PurchaseList.kvm_ip, DeviceCategory.supplier).\
        join(DeviceCategory, DeviceCategory.id == PurchaseList.device_category_id).\
        filter(PurchaseList.order_id == order_id).all()

    if not purchaselist:
        raise exceptions.MyHttpNotFound('this order has not purchase list')

    # sio = StringIO()
    sio = BytesIO()
    workbook = xlsxwriter.Workbook(sio, {'in_memory': True}) # xlwt.Workbook(encoding='ascii')   # 写到IO中
    worksheet = workbook.add_worksheet(name=order.order_num)
    # worksheet.merge_range(0, 0, 0, 5, 'aaa')  # 合并单元格
    # worksheet.write(11, 2, '=SUM(1:10)')  # 增加公式
    # worksheet.set_default_row(35)  # 设置默认行高
    style1 = workbook.add_format({'font_size': '11', 'align': 'center', 'valign': 'vcenter', 'bold': True})   # 设置风格    'bg_color': '#34A0FF',
    style2 = workbook.add_format({'font_size': '11', 'align': 'center', 'valign': 'vcenter', 'bold': False})   # 'font_color': '#217346'
    worksheet.set_column('A:H', None, style2)
    worksheet.set_column(0, 7, 20)  # 设置列宽
    title = ['序号', 'CICODE', '序列号', '型号', '配置', '价格', 'KVM IP', '供应商']
    worksheet.write_row('A1', title, style1)

    for i in range(len(purchaselist)):
        data = [
            i + 1,
            purchaselist[i][0],
            purchaselist[i][1],
            purchaselist[i][2],
            purchaselist[i][3],
            purchaselist[i][4],
            purchaselist[i][5],
            purchaselist[i][6],
        ]
        worksheet.write_row('A'+ str(i+2), data)

    workbook.close()
    sio.seek(0)		# 将byte流再从头读取,之前已经写到最后一个byte了
    resp = sio.getvalue()	# 通过getvalue函数读取IO流
    sio.close()	# 关闭IO流
    # 这里我是要同时返回IO字节流及订单编号,所以用了个list,不需要的话直接返回return resp即可
    orderdata = [resp, order.order_num]	
    return orderdata

注意事项:踩过的坑

1、StringIO与BytesIO
import StringIO

这是python2.7的用法,python3.0后这个模块归入IO模块了

from io import StringIO

但是我们这里还是用不了,会报错:

TypeError: string argument expected, got 'bytes'

所以,我们这里用另外一个模块:BytesIO,就可以了哈。

2、用flask-restful的方式实现

网上的一些案例都是一些单独的函数处理,对于flask-restful的方式需要稍微留意以下几点,否则很容易会收到如下报错:

TypeError: Object of type 'Response' is not JSON serializable

就如同上面的案例所示:
(1)我们不能为该视图方法get()指定它的marshal模型
(2)在视图get()方法中返回值不能另外带http code,直接返回response对象即可

resp = make_response(respdata[0])
 resp.headers["Content-Disposition"] = "attachment; filename={}.xlsx".format(respdata[1])
resp.headers['Content-Type'] = 'application/x-xlsx'
return resp # 这里不可以return resp, 200

参考文章:
(1).python3+xlsxwriter+flask 导出excel 作者: 科比龙篮
(2).flask中使用xlsxwriter导出excel文件 作者:潇湘旧友

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值