Pymongo结合Sanic 导出excel
前言
在Sanic项目中集成MongoDB直接使用官方的异步驱动motor配合Sanic来操作MongoDB数据库。
项目介绍
从mongodb里读出数据 导成excel 反馈给前端
安装
pip install motor
链接句柄
链接
@app.listener('before_server_start')
async def setup_db(app, loop):
app.ctx.client = AsyncIOMotorClient('mongodb://localhost:27017')
关闭
@app.listener('after_server_stop')
async def close_db(app, loop):
app.ctx.client.close()
如上文
将client 挂载给了 app.ctx 避免了 多次初始化。
excel 导出代码
# 创建一个新的 Excel 工作簿
wb = Workbook()
# 选择活动的工作表,默认是第一个
ws = wb.active
ws.title = 'Sheet1'
# 将数据转换为列表形式,便于写入 Excel
rows = [list(record.values()) for record in list_data]
# 写入表头(假设数据的第一条记录的键即为表头)
headers = list(list_data[0].keys())
ws.append(headers)
# 写入数据
for row in rows:
ws.append(row)
# 保存 Excel 文件到内存中的二进制流
with BytesIO() as output:
wb.save(output)
excel_data = output.getvalue()
# 设置响应头并发送 XLSX 文件内容
headers = {
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8',
'Content-Disposition': f'attachment; filename={urllib.parse.quote(collection_name)}.xlsx'
}
return response.raw(excel_data, headers=headers)
如上文 list_data 是[{},{},{}] 这样的形式。
完整代码
import urllib
from io import BytesIO
from sanic import Sanic, response
from pymongo import MongoClient
from openpyxl import Workbook
from sanic_jinja2 import SanicJinja2
from motor.motor_asyncio import AsyncIOMotorClient
app = Sanic(__name__)
jinja = SanicJinja2(app)
app.config.JINJA2_TEMPLATE_DIR = './templates'
# 连接MongoDB
@app.listener('before_server_start')
async def setup_db(app, loop):
app.ctx.client = AsyncIOMotorClient('mongodb://localhost:27017')
# 连接到 MongoDB
async def get_mongo_data(collection_name):
db = app.ctx.client['xxx']
collection = db.get_collection(collection_name)
# 查询数据并返回
async def fetch_data():
cursor = collection.find({}, {'_id': 0})
data = []
async for record in cursor:
data.append(dict(record))
return data
result = await fetch_data()
return result
# 定义一个路由来渲染包含按钮的 HTML 页面
@app.route('/')
async def index(request):
db = app.ctx.client['京东']
collection_names = await db.list_collection_names()
return jinja.render('index.html', request, collection_names=sorted(collection_names))
@app.route('/export')
async def export_data(request):
collection_name = request.args.get('collection_name') # 从查询参数中获取集合名
if not collection_name:
return response.json({"error": "Missing required parameter 'collection_name'"}, status=400)
mongo_data = await get_mongo_data(collection_name)
# 创建一个新的 Excel 工作簿
wb = Workbook()
# 选择活动的工作表,默认是第一个
ws = wb.active
ws.title = 'Sheet1'
# 将数据转换为列表形式,便于写入 Excel
rows = [list(record.values()) for record in mongo_data]
# 写入表头(假设数据的第一条记录的键即为表头)
headers = list(mongo_data[0].keys())
ws.append(headers)
# 写入数据
for row in rows:
ws.append(row)
# 保存 Excel 文件到内存中的二进制流
with BytesIO() as output:
wb.save(output)
excel_data = output.getvalue()
# 设置响应头并发送 XLSX 文件内容
headers = {
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8',
'Content-Disposition': f'attachment; filename={urllib.parse.quote(collection_name)}.xlsx'
}
return response.raw(excel_data, headers=headers)
# 在请求结束时关闭连接(可选,根据实际需求)
@app.listener('after_server_stop')
async def close_db(app, loop):
app.ctx.client.close()
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8888)
前端代码暂不展示。