小明:最近我在做一个教材征订管理系统,感觉下载功能有点难搞。
小李:哦?你遇到了什么问题?
小明:我需要让管理员可以下载学生提交的教材征订单。但不知道怎么实现。
小李:那你可以用后端生成PDF或者Excel文件,然后提供下载链接。
小明:对,但是具体怎么做呢?有没有现成的库可以用?
小李:当然有。比如Python中可以用ReportLab生成PDF,或者用pandas导出Excel。
小明:那我要先从数据库里查出数据,再生成文件。
小李:没错。我们可以先写一个函数,根据查询结果生成文件。
小明:那我可以先展示一下数据库结构吗?
小李:好的,假设你的数据库有一个表叫orders,里面有student_id、course_name、book_name、quantity这些字段。
小明:明白了。那我该怎么写代码呢?
小李:我们先用Flask作为后端框架,然后用SQLAlchemy连接数据库。
小明:好的,那我来写一个简单的例子。
小李:你可以先创建一个路由,当用户访问/download时,触发下载功能。
小明:那具体的下载逻辑呢?
小李:我们可以使用pandas将数据转换为DataFrame,然后导出为Excel文件。
小明:那代码应该是什么样的?
小李:让我给你写个示例代码。
小明:太好了,快给我看看。
小李:
from flask import Flask, send_file
import pandas as pd
from sqlalchemy import create_engine
app = Flask(__name__)
# 数据库连接配置
engine = create_engine('mysql+pymysql://user:password@localhost/dbname')
@app.route('/download')
def download():
# 查询数据库
query = "SELECT * FROM orders"
df = pd.read_sql(query, engine)
# 导出为Excel
file_path = 'orders.xlsx'
df.to_excel(file_path, index=False)
# 返回文件
return send_file(file_path, as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
小明:这段代码看起来很清晰,但我需要注意哪些依赖?
小李:你需要安装flask、pandas和sqlalchemy,还有mysql-connector-python。
小明:明白了。那如果我要支持PDF格式呢?
小李:可以用ReportLab库生成PDF文件。
小明:那代码应该怎么改?
小李:我们可以用ReportLab来生成PDF,然后再返回给用户。
小明:那我来试试看。
小李:
from flask import Flask, send_file
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors
from sqlalchemy import create_engine
app = Flask(__name__)
engine = create_engine('mysql+pymysql://user:password@localhost/dbname')
@app.route('/download_pdf')
def download_pdf():
query = "SELECT * FROM orders"
df = pd.read_sql(query, engine)
# 创建PDF
file_path = 'orders.pdf'
doc = SimpleDocTemplate(file_path, pagesize=letter)
data = [df.columns.tolist()] + df.values.tolist()
table = Table(data)
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.lightblue),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
doc.build([table])
return send_file(file_path, as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
小明:这个代码也很好,不过我需要安装reportlab库。
小李:是的,记得用pip install reportlab。
小明:那这两个下载功能怎么整合到系统中呢?
小李:可以在前端页面上添加两个按钮,分别调用不同的下载接口。
小明:那前端代码应该怎么写?
小李:可以用HTML和JavaScript来实现。
小明:那你能给我一个例子吗?
小李:
<!DOCTYPE html>
<html>
<head>
<title>教材征订系统</title>
</head>
<body>
<h1>教材征订管理系统</h1>
<p><a href="/download">下载Excel文件</a></p>
<p><a href="/download_pdf">下载PDF文件</a></p>
</body>
</html>
小明:这样就能直接点击下载了。
小李:没错,这就是一个完整的下载功能实现。

小明:那有没有更高级一点的方式?比如动态生成文件名?
小李:当然可以,可以在下载时根据时间或用户ID生成唯一的文件名。
小明:那我该怎么修改代码?
小李:可以使用datetime模块获取当前时间,然后拼接成文件名。
小明:那我来试试看。
小李:
from datetime import datetime
@app.route('/download')
def download():
query = "SELECT * FROM orders"
df = pd.read_sql(query, engine)
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
file_path = f'orders_{current_time}.xlsx'
df.to_excel(file_path, index=False)
return send_file(file_path, as_attachment=True)
小明:这样每次下载都会生成一个不同的文件名,避免覆盖。
小李:对,这是一个很好的做法。
小明:那我还可以在下载前进行权限验证吗?
小李:当然可以,比如检查用户是否登录,是否有下载权限。
小明:那我该怎么做?
小李:可以在路由中加入权限判断逻辑。
小明:那能给我举个例子吗?
小李:
from flask import session
@app.route('/download')
def download():
if 'user' not in session:
return "无权访问", 403
# 继续之前的下载逻辑
...
return send_file(...)
小明:这样就能控制只有登录用户才能下载了。
小李:没错,这就是一个完整的下载功能实现。
小明:谢谢你,这对我帮助很大。
小李:不客气,希望你顺利完成项目。
小明:嗯,我会继续努力的。
