使 Flask Marshmallow 嵌套模式与我的 API 路线一起工作

Make Flask Marshmallow NestedSchema work wtth my API route

我正在使用 Flask、SQLAlchemy 和 Marshmallow 制作 APi。

模型已定义,数据库已填充数据,并在点击视图时。我从 NonProfitSchema.

中获取了所有字段 JSON 的内容
class NonprofitSchema(ma.ModelSchema):
    class Meta:
        model = Nonprofit

        # To specialize fields something like so
        fields = ('id', 'name', 'ein', 'ico', 'street', 'city', 'state', 'zipcode', 'group', 'subsection', 'affiliation', 'classification', 'ruling',
 'deductability', 'foundation', 'activity', 'organization', 'status', 'tax_period', 'asset_cd','income_cd', 'filing_req_cd', 'pf_filing_req_cd',
 'acct_pd', 'asset_amt', 'income_amt', 'revenue_amt', 'ntee', 'sort_name', 'activity_full')

我试图从中创建一个新架构,return 只有数据的一个子集

class AddressSchema(NonProfitSchema):

    from marshmallow import fields 
    address = fields.Nested(NonprofitSchema(only=("street", "city", "state", "zipcode",)))  

我的 view.py 中有这样设置的路线:

@api_blueprint.route("/api/orgs/id/<int:id>/", methods=["GET"]) def get_org_by_id(id):
    org = Nonprofit.query.get(id)
    return npschema.jsonify(org)

@api_blueprint.route("/api/orgs/address/<int:id>/", methods=["GET"]) def get_org_by_id_address(id):
    org = Nonprofit.query.get(id)
    return addyschema.jsonify(org)

但是,在浏览器中访问它们时。它们 return 完全相同,是 NonprofitSchema

的整个数据库模型

我想不可能用 Schema 做数据子集,对吧?

或者,您可以将此逻辑直接插入 jsonify 步骤

org = Nonprofit.query.get(id)
only_these_fields = ["street", "city", "state", "zipcode"]
return addyschema.jsonify({key: value for key, value in org.items() if key in only_these_fields}

我没有全貌,但我觉得将父架构嵌套在子架构中很奇怪。

这个(未经测试)怎么样?

class AddressSchema(NonProfitSchema):

    class Meta:
        fields = ("street", "city", "state", "zipcode",)

我应该更新我的答案。当我和用户 c8999c 3f964f64 基本上也是这么想的,确实有点效果。在我的例子中,对象上的 "jsonify" 不会像在他的示例中那样工作我构建了一个单独的函数,因为没有 items 属性。因此,制作一个使用 get 属性的过滤器:

def jsonfilter(obj, attrlist):

    resp = {}
    for attr in attrlist:
        resp[attr] = getattr(obj,attr)
    return resp

然后修改函数以便使用它:

@api_blueprint.route("/api/orgs/id/<int:id>/address", methods=["GET"])
def get_org_address_by_id(id):
    org = Nonprofit.query.get(id)
    only_these_fields = ["id", "ein", "name", "street", "city", "state", "zipcode"]
    return jsonify(jsonfilter(org, only_these_fields))

我成功了。

在查看 Flask 和 Flask-Marshmallow 文档后,另一种更简单的方法是简单地实例化模型的新 class 对象,并传入字段。

@api_blueprint.route("/api/orgs/id/<int:id>/address", methods=["GET"])
def get_org_address_by_id(id):
    org = Nonprofit.query.get(id)
    only_these_fields = ["id", "ein", "name", "street", "city", "state", "zipcode"]
    addyschema = NonprofitSchema(fields=only_these_fields)
    return addyschema.jsonify(org)

我选择反对这种方法,因为我更喜欢只需要一个单独的 class 对象并且调用过滤器方法感觉更好。