Quickstart

Introduction

flask-smorest makes a few assumptions about how the code should be structured.

The application should be split in Blueprint. It is possible to use basic Flask view functions but it is generally a good idea to use Flask MethodView classes instead.

Marshmallow Schema are used to serialize parameters and responses.

Request and response bodies are serialized as JSON.

A view function only has one successful response type and status code. All other possible responses are errors.

Simple Example

Here is a basic “Petstore example”, where The Pet class is an imaginary ORM.

First instantiate an Api with a Flask application.

from flask import Flask
from flask.views import MethodView
import marshmallow as ma
from flask_smorest import Api, Blueprint, abort

from .model import Pet

app = Flask(__name__)
app.config['API_TITLE'] = 'My API'
app.config['API_VERSION'] = 'v1'
app.config['OPENAPI_VERSION'] = '3.0.2'
api = Api(app)

Define a marshmallow Schema to expose the model.

class PetSchema(ma.Schema):
    id = ma.fields.Int(dump_only=True)
    name = ma.fields.String()

Define a marshmallow Schema to validate the query arguments.

class PetQueryArgsSchema(ma.Schema):
    name = ma.fields.String()

Instantiate a Blueprint.

blp = Blueprint(
    'pets', 'pets', url_prefix='/pets',
    description='Operations on pets'
)

Use MethodView classes to organize resources, and decorate view methods with Blueprint.arguments and Blueprint.response to specify request deserialization and response serialization respectively.

Use abort to return errors, passing kwargs used by the error handler (handle_http_exception) to build the error response.

@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:
            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.')

Finally, register the Blueprint in the Api.

api.register_blueprint(blp)