Flask与MongoDB文档编辑问题:GET正常但POST无法更新数据
Hey there! Let's walk through the issues in your code that are blocking the POST request from updating your MongoDB document. I'll break down each problem and show you how to fix them step by step.
1. Wrong Query Filter in update_one
Your current update logic uses {"id": id} to target the document, but MongoDB uses _id as the default primary key (you even use ObjectId(id) to fetch the document in the GET request!). This means your update is looking for a document with a field named id matching the string value of id—which doesn't exist in your database.
Fix:
Update the query filter to use the correct _id field with ObjectId conversion:
books.update_one({"_id": ObjectId(id)}, { "$set": { "title": request.form.get('title'), "author": request.form.get('author'), "edition": request.form.get('edition'), "price": request.form.get('price'), # We'll fix the image handling next "date": datetime.datetime.utcnow() } })
2. Improper Handling of File Uploads
You're trying to save request.files.get('image') directly to MongoDB, but this is a FileStorage object—not a value the database can store. You have two common options here:
- Save the file to your server's filesystem and store the file path in MongoDB.
- Store the file's binary data directly (use GridFS for files larger than 16MB).
Example Fix (Save File Path):
First, create an uploads folder in your project root. Then add this logic to handle the file:
from werkzeug.utils import secure_filename import os # Configure upload settings at the top of your app UPLOAD_FOLDER = 'uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'} def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS'] # Inside your POST handler: update_data = { "title": request.form.get('title'), "author": request.form.get('author'), "edition": request.form.get('edition'), "price": request.form.get('price'), "date": datetime.datetime.utcnow() } if 'image' in request.files: file = request.files['image'] if file.filename != '' and allowed_file(file.filename): filename = secure_filename(file.filename) file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(file_path) update_data['image'] = file_path # Store the relative path in DB
3. Missing POST Request Branch
Right now, your update code runs every time the route is hit—even for GET requests. This means when a user first loads the edit page (GET), it tries to update the document with empty form data, which fails silently.
Fix:
Wrap all update logic inside an if request.method == 'POST' block, mirroring your GET handling:
@app.route('/edit_book/<id>', methods=['POST', 'GET']) def edit_book_id(id): books = connexion.db.books item = books.find_one({'_id': ObjectId(id)}) if request.method == 'GET': if session['username'] is not None: return render_template('edit_book.html', username=session['username'], mybooks=item) # Add redirect to login if user is not authenticated return redirect(url_for('login')) elif request.method == 'POST': # Add the image handling code here first update_data = { "title": request.form.get('title'), "author": request.form.get('author'), "edition": request.form.get('edition'), "price": request.form.get('price'), "date": datetime.datetime.utcnow() } if 'image' in request.files: file = request.files['image'] if file.filename != '' and allowed_file(file.filename): filename = secure_filename(file.filename) file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(file_path) update_data['image'] = file_path # Perform the update result = books.update_one({"_id": ObjectId(id)}, {"$set": update_data}) # Optional: Add feedback based on update result if result.modified_count > 0: return 'Updated successfully!' else: return 'No changes detected or document not found.'
4. (Optional) Explicit Form Action
Your form uses action="", which usually works, but explicitly setting it to the edit route avoids any potential routing issues:
<form action="/edit_book/{{mybooks._id}}" method="POST" enctype=multipart/form-data> <!-- Your existing form fields --> </form>
Quick Debug Tips
- Double-check you've imported
ObjectIdcorrectly:from bson.objectid import ObjectId - Add authentication checks to the POST branch (right now, unauthenticated users could send update requests)
- Use
print(request.form)andprint(request.files)inside the POST handler to see exactly what data is being sent to the server
内容的提问来源于stack exchange,提问作者Adil Blanco

