如何在Flask项目的mod1中导入复用mod2的文件上传功能?
问题:Flask主模块mod1复用mod2的文件上传功能无效果
背景
目标是在主模块mod1.py中实现文件上传,文件保存至/static/img/目录,但尝试后无文件保存。希望从同根目录的mod2.py导入复用上传功能,已添加空__init__.py,未使用Django。目前无报错但文件未保存,求方向判断及具体解决建议。
项目结构
root/ __init__.py mod1.py mod2.py
mod1 可用代码
from flask import Flask, redirect, render_template, request, url_for app = Flask(__name__) app.config["DEBUG"] = True comments = [] @app.route("/", methods=["GET", "POST"]) def index(): if request.method == "GET": return render_template("main_page.html", comments=comments) comments.append(request.form["contents"]) return redirect(url_for('index'))
mod2 可用代码
import os from flask import Flask, flash, redirect, render_template, request, url_for from werkzeug.utils import secure_filename from flask_uploads import IMAGES, UploadSet, configure_uploads UPLOAD_FOLDER = 'uploads' ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'docx'} app = Flask(__name__) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 photos = UploadSet("photos", IMAGES) app.config["UPLOADED_PHOTOS_DEST"] = "static/img" app.config["SECRET_KEY"] = os.urandom(24) configure_uploads(app, photos) def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/', methods=['GET', 'POST']) def upload(): if request.method == 'POST' and 'photo' in request.files: photos.save(request.files['photo']) flash("Photo saved successfully.") return render_template('upload.html') return render_template('upload.html') from flask import send_from_directory @app.route('/uploads/<filename>') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) from werkzeug.middleware.shared_data import SharedDataMiddleware app.add_url_rule('/uploads/<filename>', 'uploaded_file', build_only=True) app.wsgi_app = SharedDataMiddleware(app.wsgi_app, { '/uploads': app.config['UPLOAD_FOLDER'] })
mod1 中的尝试代码
import os from flask import Flask, flash, redirect, render_template, request, url_for from werkzeug.utils import secure_filename from flask import Request from flask_uploads import IMAGES, UploadSet, configure_uploads from mod1 import getPhotos from mod1 import upload UPLOAD_FOLDER = 'uploads' ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'docx'} app = Flask(__name__) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 photos = getPhotos() app.config["UPLOADED_PHOTOS_DEST"] = "static/img" app.config["SECRET_KEY"] = os.urandom(24) configure_uploads(app, photos) def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS upload() """ #as a function @app.route('/', methods=['GET', 'POST']) def upload(): if request.method == 'POST' and 'photo' in request.files: photos.save(request.files['photo']) flash("Photo saved successfully.") return render_template('upload.html') return render_template('upload.html') """ from flask import send_from_directory @app.route('/uploads/<filename>') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) from werkzeug.middleware.shared_data import SharedDataMiddleware app.add_url_rule('/uploads/<filename>', 'uploaded_file', build_only=True) app.wsgi_app = SharedDataMiddleware(app.wsgi_app, { '/uploads': app.config['UPLOAD_FOLDER'] })
问题分析与解决建议
方向判断
你的方向是对的——复用已有模块的上传功能是合理的,但尝试代码中存在几个关键错误导致功能失效。
具体错误点
- 错误的导入路径:尝试代码中写了
from mod1 import getPhotos, upload,但这两个对象是在mod2里定义的,应该改为from mod2 import photos, upload。 - 重复创建Flask实例:mod1本身已经有一个
app实例,尝试代码里又重新创建了一个新的app,导致配置和路由都绑定到了错误的实例上,运行时实际使用的是mod1原来的app,而不是你配置了上传功能的新app。 - 直接调用
upload()函数:upload()是一个路由视图函数,需要由Flask的请求调度来触发,直接调用它不会处理请求,也不会绑定路由。 - 路由冲突:mod1原有
@app.route("/")和上传功能的/路由冲突,需要修改上传路由的路径,比如改为/upload。
修正后的mod1代码
import os from flask import Flask, redirect, render_template, request, url_for from mod2 import photos, upload # 正确导入mod2中的对象 app = Flask(__name__) app.config["DEBUG"] = True app.config["UPLOADED_PHOTOS_DEST"] = "static/img" app.config["SECRET_KEY"] = os.urandom(24) app.config['UPLOAD_FOLDER'] = 'uploads' # 配置上传集合到当前app实例 from flask_uploads import configure_uploads configure_uploads(app, photos) comments = [] @app.route("/", methods=["GET", "POST"]) def index(): if request.method == "GET": return render_template("main_page.html", comments=comments) comments.append(request.form["contents"]) return redirect(url_for('index')) # 注册mod2中的上传路由,修改路径避免冲突 app.add_url_rule('/upload', view_func=upload, methods=['GET', 'POST']) # 复用mod2中的文件访问路由 from mod2 import uploaded_file app.add_url_rule('/uploads/<filename>', view_func=uploaded_file) # 添加共享数据中间件 from werkzeug.middleware.shared_data import SharedDataMiddleware app.add_url_rule('/uploads/<filename>', 'uploaded_file', build_only=True) app.wsgi_app = SharedDataMiddleware(app.wsgi_app, { '/uploads': app.config['UPLOAD_FOLDER'] })
额外注意事项
- 确保
static/img目录存在,Flask不会自动创建目录,运行前手动创建:mkdir -p static/img。 - 上传表单的
enctype必须设为multipart/form-data,否则文件无法正确传递:<!-- 在upload.html中 --> <form method="POST" enctype="multipart/form-data"> <input type="file" name="photo"> <button type="submit">上传</button> </form> - 检查mod2中的
UPLOAD_FOLDER和UPLOADED_PHOTOS_DEST路径是否是相对当前项目根目录的,避免路径错误。
内容的提问来源于stack exchange,提问作者Kamus Suwanto
相关产品推荐
相关产品推荐

