0

我试图了解 Marshmallow Schemas 的内省是如何工作的。这是一个简单的代码示例:

import os

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from pprint import pprint


db_file = "database.db"
if os.path.isfile(db_file):
    os.remove(db_file)

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{db_file}"
app.app_context().push()

db = SQLAlchemy(app)
ma = Marshmallow(app)


class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    age = db.Column(db.Integer)


class MySchema(ma.Schema):
    class Meta:
        model = Person
        sqla_session = db.session
    

db.create_all()

alice = Person(name="Alice", age=25)
bob = Person(name="Bob", age=26)

db.session.add(alice)
db.session.add(bob)
db.session.commit()

persons = Person.query.all()
schema = MySchema(many=True)
result = schema.dump(persons)
pprint(result)

当我运行这个脚本时,我得到的结果是[{}, {}]. 这告诉我它确实Person从数据库中检索了对象,但是Schema没有字段,所以它只返回空字典。我希望这个脚本返回[{"id": 0, "name": "Alice", "age": 25}, {"id": 1, "name": "Bob", "age": 26}],或类似的东西。显然,数据库模型的自省并没有发生。为什么不?我应该如何修改这个脚本以获得预期的结果?

为了完整起见,我使用的是 Python 3.8.5,pip freeze在我的环境中 a 的结果是这样的:

alembic==1.4.3
aniso8601==8.0.0
attrs==20.2.0
click==7.1.2
Flask==1.1.2
flask-marshmallow==0.14.0
Flask-Migrate==2.5.3
flask-restx==0.2.0
Flask-Script==2.0.6
Flask-SQLAlchemy==2.4.4
itsdangerous==1.1.0
Jinja2==2.11.2
jsonschema==3.2.0
Mako==1.1.3
MarkupSafe==1.1.1
marshmallow==3.8.0
marshmallow-sqlalchemy==0.23.1
psycopg2-binary==2.8.6
pyrsistent==0.17.3
python-dateutil==2.8.1
python-editor==1.0.4
pytz==2020.1
six==1.15.0
SQLAlchemy==1.3.20
Werkzeug==0.16.1

注意:我知道我可以通过MySchema像这样修改我的类来让它工作:

class MySchema(ma.SQLAlchemySchema):
    class Meta:
        model = Person
        sqla_session = db.session
    
    id = ma.auto_field()
    name = ma.auto_field()
    age = ma.auto_field()

但这违背了完全自动内省的目的。我想避免在两个地方定义字段。

4

1 回答 1

0

感谢 pjcunningham 的评论,我设法让它发挥作用。就像他提到的那样,所要做的就是替换ma.SQLAlchemySchemama.SQLAlchemyAutoSchema. 在此更改之后,脚本返回了所需的结果。

于 2020-10-16T19:34:49.237 回答