I'm making an APi using Flask, SQLAlchemy, and Marshmallow.
The model is defined and the database is populated with data and when the view is hit. I get all the fields JSON content from NonProfitSchema
.
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')
I was trying to make a new Schema from this and return only a subset of the data with so below
class AddressSchema(NonProfitSchema):
from marshmallow import fields
address = fields.Nested(NonprofitSchema(only=("street", "city", "state", "zipcode",)))
I had routes in my view.py set up as so:
@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)
However, when accessing them in a browser. They both return the exact same thing which is the entire database model of NonprofitSchema
I'm supposing it's not possible to do subsets of data with the Schema, right?
I should update the answer that I went with. While I and user
c8999c 3f964f64 basically thought of the same way and that will indeed sort of work. In my case, "jsonify" on the object wouldnt work as in his example I built a separate function as there is no items
attribute. So with a filter made that uses get attribute as so:
def jsonfilter(obj, attrlist):
resp = {}
for attr in attrlist:
resp[attr] = getattr(obj,attr)
return resp
Then modifying the function as so to use it:
@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))
I was able to make it work.
Alternatively and a much simpler way after reviewing the Flask and Flask-Marshmallow documentation is to simply instantiate a new class object of the model with fields passed in.
@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)
I opted against this method because I prefer to only need one separate class object and calling a filter method feels better.