To set up a flask-smorest API, follow these steps:
- Initialize the API: Instantiate the
Api class with your Flask app and configure API metadata using app.config. - Define Schemas: Create Marshmallow schemas for your data models and for validating query arguments.
- Create a Blueprint: Use
Blueprint to define a logical grouping of routes, including a url_prefix and description. - Implement MethodViews: Use
@blp.arguments to handle request deserialization and @blp.response to handle response serialization. - Handle Errors: Use the
abort function to return errors, passing a status code and a message (which is passed to the error handler). - Register the Blueprint: Register your blueprint with the
Api instance using api.register_blueprint(blp).
from flask import Flask
from flask.views import MethodView
import marshmallow as ma
from flask_smorest import Api, Blueprint, abort
# 1. Initialize API
app = Flask(__name__)
app.config["API_TITLE"] = "My API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.2"
api = Api(app)
# 2. Define Schemas
class PetSchema(ma.Schema):
id = ma.fields.Int(dump_only=True)
name = ma.fields.String()
class PetQueryArgsSchema(ma.Schema):
name = ma.fields.String()
# 3. Create Blueprint
blp = Blueprint("pets", "pets", url_prefix="/pets", description="Operations on pets")
# 4. Implement MethodViews
@blp.route("/")
class Pets(MethodView):
@blp.arguments(PetQueryArgsSchema, location="query")
@blp.response(200, PetSchema(many=True))
def get(self, args):
"""List pets"""
return Pet.get(filters=args)
@blp.arguments(PetSchema)
@blp.response(201, PetSchema)
def post(self, new_data):
"""Add a new pet"""
item = Pet.create(**new_data)
return item
@blp.route("/<pet_id>")
class PetsById(MethodView):
@blp.response(200, PetSchema)
def get(self, pet_id):
"""Get pet by ID"""
try:
item = Pet.get_by_id(pet_id)
except ItemNotFoundError:
# 5. Handle Errors
abort(404, message="Item not found.")
return item
@blp.arguments(PetSchema)
@blp.response(200, PetSchema)
def put(self, update_data, pet_id):
"""Update existing pet"""
try:
item = Pet.get_by_id(pet_id)
except ItemNotFoundError:
abort(404, message="Item not found.")
item.update(update_data)
item.commit()
return item
@blp.response(204)
def delete(self, pet_id):
"""Delete pet"""
try:
Pet.delete(pet_id)
except ItemNotFoundError:
abort(404, message="Item not found.")
# 6. Register Blueprint
api.register_blueprint(blp)