You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 ObjectId correctly: from bson.objectid import ObjectId
  • Add authentication checks to the POST branch (right now, unauthenticated users could send update requests)
  • Use print(request.form) and print(request.files) inside the POST handler to see exactly what data is being sent to the server

内容的提问来源于stack exchange,提问作者Adil Blanco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:45:28