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

树莓派上基于Flask与MySQL数据库的RESTful API调试问题求助

解决Flask+Marshmallow SQLAlchemy POST请求中的AttributeError问题

我一看你这报错就知道核心问题出在哪了——SQLAlchemySchema默认的load()方法返回的是字典,不是你的Todo模型实例,所以你调用create()方法才会各种报错。咱们一步步来把这个问题搞定:

问题根源拆解

  1. 第一个错误AttributeError: 'dict' object has no attribute 'create':你用todo_schema.load(data)拿到的是个字典,而字典肯定没有create()方法啊,这是因为SQLAlchemySchema默认不返回模型实例。
  2. 第二个错误TypeError: create() missing 1 required positional argument: 'self':你改成Todo.create()后,又把实例方法当成类方法调用了,create()是需要通过Todo实例来调用的,直接用类调用当然缺self参数。

具体解决方案

1. 修改TodoSchema,让它返回模型实例

在TodoSchema的Meta类里加一行load_instance=True,这样load()方法就会返回Todo的实例,而不是字典:

class TodoSchema(SQLAlchemySchema):
    class Meta(SQLAlchemySchema.Meta):
        model = Todo
        sqla_session = db.session
        load_instance = True  # 关键配置:启用实例加载
    id = fields.Number(dump_only=True)
    title = fields.String(required=True)
    todo_description = fields.String(required=True)

2. 恢复原有的create()调用逻辑

现在todo_schema.load(data)能拿到Todo实例了,你可以把代码改回最初的写法:

@app.route('/api/v1/todo', methods=['POST'])
def create_todo():
    data = request.get_json()
    print(data)
    todo_schema = TodoSchema()
    todo = todo_schema.load(data)
    result = todo_schema.dump(todo.create())
    return make_response(jsonify({"todo": result}), 200)

3. 顺便解决启动时的SQLAlchemy警告

在你的app配置里加上这一行,消除那个烦人的SQLALCHEMY_TRACK_MODIFICATIONS警告:

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

4. 适配Flask 2.x+的上下文问题

我还帮你加了应用上下文包裹db.create_all(),避免在新版本Flask里创建表时出现上下文错误:

with app.app_context():
    db.create_all()

修改后的完整代码

from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from marshmallow import fields
from marshmallow_sqlalchemy import SQLAlchemySchema
import json

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@localhost:3306/todo'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 消除警告
db = SQLAlchemy(app)

# Model
class Todo(db.Model):
    __tablename__ = "todos"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(20))
    todo_description = db.Column(db.String(100))

    def create(self):
        db.session.add(self)
        db.session.commit()
        return self

    def __init__(self, title, todo_description):
        self.title = title
        self.todo_description = todo_description

    def __repr__(self):
        return f"{self.id}"

# 用上下文包裹表创建操作
with app.app_context():
    db.create_all()

class TodoSchema(SQLAlchemySchema):
    class Meta(SQLAlchemySchema.Meta):
        model = Todo
        sqla_session = db.session
        load_instance = True  # 启用实例加载
    id = fields.Number(dump_only=True)
    title = fields.String(required=True)
    todo_description = fields.String(required=True)

@app.route('/api/v1/todo', methods=['POST'])
def create_todo():
    data = request.get_json()
    print(data)
    todo_schema = TodoSchema()
    todo = todo_schema.load(data)
    result = todo_schema.dump(todo.create())
    return make_response(jsonify({"todo": result}), 200)

@app.route('/api/v1/todo', methods=['GET'])
def index():
    get_todos = Todo.query.all()
    todo_schema = TodoSchema(many=True)
    todos = todo_schema.dump(get_todos)
    return make_response(jsonify({"todos": todos}))

@app.route('/api/v1/todo/<id>', methods=['GET'])
def get_todo_by_id(id):
    get_todo = Todo.query.get(id)
    todo_schema = TodoSchema()
    todo = todo_schema.dump(get_todo)
    return make_response(jsonify({"todo": todo}))

最后检查

确保你的树莓派上MariaDB服务在运行,todo数据库已经创建,配置里的用户名和密码也没问题,然后再用Postman发POST请求,应该就能正常创建Todo条目了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:12:32