【问题标题】:Empty Json using Flask-Marshmallow and SQLAlchemy使用 Flask-Marshmallow 和 SQLAlchemy 的空 Json
【发布时间】:2021-08-04 07:09:11
【问题描述】:

我正在尝试创建一个端点以从两个表 indicatormetadata 返回数据,因此我使用indicator = db.relationship('Indicator', backref='metadatas')indicator_id = db.Column(db.Integer, db.ForeignKey('indicator.id')) 创建了下面的模型,但是当我调用api/indicators我得到了空的json,你可以在最后看到,为什么?

models.py

from datetime import datetime
from app import db, ma

class Indicator(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    unique_key = db.Column(db.String(32))
    name = db.Column(db.String(255))
    short_name = db.Column(db.String(255))
    valid = db.Column(db.Boolean)
    created_at = db.Column(db.DateTime())
    last_updated_at = db.Column(db.DateTime())

class Metadata(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    indicator_id = db.Column(db.Integer, db.ForeignKey('indicator.id'))
    indicator = db.relationship('Indicator', backref='metadatas')
    type = db.Column(db.String(255))
    inputs = db.Column(db.String(255))
    options = db.Column(db.String(255))
    outputs = db.Column(db.String(255))

class IndicatorSchema(ma.SQLAlchemySchema):
    class Meta:
        model = Indicator 

    id: ma.auto_field()
    unique_key: ma.auto_field()
    name: ma.auto_field()
    short_name: ma.auto_field()
    valid: ma.auto_field()

class MetadataSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = Metadata
        include_fk = True

您可以在下面看到其他文件:

app.py

from flask_jwt_extended import JWTManager
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow

app = Flask(__name__)
app.config["JWT_SECRET_KEY"] = "fe7e8955db51c0ff78550419434128cb"
app.config["JWT_ACCESS_TOKEN_EXPIRES "] = 28800
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:////tmp/test.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['JSON_SORT_KEYS'] = False

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

controller.py

from flask_jwt_extended import jwt_required, create_access_token, get_jwt_identity
from flask import Flask, request, jsonify
from models import Indicator, Metadata, IndicatorSchema, MetadataSchema
from config import conn_string
from app import app, db
import services
import hashlib
import json

@app.route('/api/indicators', methods=['GET'])
@jwt_required()
def indicators():
    short_name = request.args.get('short_name',None)

    if short_name is not None:
        indicator = Indicator.query.filter_by(short_name = short_name).first()
        indicator_schema = IndicatorSchema()
        output = indicator_schema.dump(indicator)

    else:
        indicators = Indicator.query.all()
        indicators_schema = IndicatorSchema(many=True)
        output = indicators_schema.dump(indicators)

    return jsonify(output), 200

当我调用 /api/indicators 时,我得到了响应 200 但 JSON 为空:

$ http :5000/api/indicators 
HTTP/1.0
Content-Type: application/json
Server: Werkzeug/2.0.0 Python/3.8.5
[
    {},
    {},
    {},
    {},
    {},
    {}
]

【问题讨论】:

    标签: python flask flask-sqlalchemy flask-marshmallow


    【解决方案1】:

    我认为有两个问题:

    1. 您应该在 Indicator 模型上定义关系(一个包含许多元数据的指标)
    2. 我相信您正在寻找元属性 include_relationships,因为您希望返回的不仅仅是外键 ID

    您的代码进行了调整:

    from datetime import datetime
    from app import db, ma
    
    class Indicator(db.Model):
        __tablename__ = "indicator"
        id = db.Column(db.Integer, primary_key=True)
        unique_key = db.Column(db.String(32))
        name = db.Column(db.String(255))
        short_name = db.Column(db.String(255))
        valid = db.Column(db.Boolean)
        created_at = db.Column(db.DateTime())
        last_updated_at = db.Column(db.DateTime())
        metadatas = db.relationship('Metadata', backref='indicator')
    
    class Metadata(db.Model):
        __tablename__ = "metadata"
        id = db.Column(db.Integer, primary_key=True)
        indicator_id = db.Column(db.Integer, db.ForeignKey('indicator.id'))
        type = db.Column(db.String(255))
        inputs = db.Column(db.String(255))
        options = db.Column(db.String(255))
        outputs = db.Column(db.String(255))
    
    class IndicatorSchema(ma.SQLAlchemyAutoSchema):
        class Meta:
            model = Indicator
            include_relationships = True
    
        id: ma.auto_field()
        unique_key: ma.auto_field()
        name: ma.auto_field()
        short_name: ma.auto_field()
        valid: ma.auto_field()
    
    class MetadataSchema(ma.SQLAlchemyAutoSchema):
        class Meta:
            model = Metadata
    

    【讨论】:

    • 我之前做过这个,但官方文档和我的模型相似。我应用了你的模型,但我仍然在 JSON 中得到空对象,很奇怪!我将class IndicatorSchema(ma.SQLAlchemySchema): 更改为class IndicatorSchema(ma.SQLAlchemyAutoSchema): 并且jsonify 工作......
    • 在没有include_relationships 的情况下是否可以工作?我已经更新了我的答案,让 IndicatorSchema 继承自 SQLAlchemyAutoSchema
    • 成功了,谢谢,您知道如何显示所有元数据字段,而不仅仅是 id 吗? "metadatas": [1]
    • 这就是include_relationships 应该做的,显示所有字段。您能否发布您更新的代码,以便我可以看到您实际使用的是什么?
    • 我正在使用您答案中的确切代码
    猜你喜欢
    • 2021-04-19
    • 2021-06-27
    • 2017-06-08
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    • 2022-07-03
    • 2017-03-26
    • 1970-01-01
    相关资源
    最近更新 更多