Introduction
I created a library that allows you to easily develop an API using SQLAlchemy models: safrs. In this series I will demonstrate how to use the library to implement an API similar to this live demo. The exposed endpoints are compliant with the json:api specification. This means the API provides all functionality you'd expect from a JSON API, such as relationships, resource linkage, pagination, filtering, sorting, and much more. An OpenAPI (fka swagger) frontend is automatically generated to allow API exploration.
In this first part, I explain how to build a simple API app. The source code of this app can be found here
Installation
The safrs package can be installed by cloning the github repository or by using pip, e.g.:
python3 -m pip install safrs --user
SQLAlchemy Objects
The objects that will be exposed are almost identical to SQLAlchemy models. The following class for example, describes attributes and a relationship for an object called User
, based on a Users
table.
class User(SAFRSBase, db.Model):
"""
description: User description
"""
__tablename__ = "Users"
id = db.Column(db.String, primary_key=True)
name = db.Column(db.String, default="")
email = db.Column(db.String, default="")
books = db.relationship("Book", back_populates="user", lazy="dynamic")
Similar to the User
class, a Book
class is created:
class Book(SAFRSBase, db.Model):
"""
description: Book description
"""
__tablename__ = "Books"
id = db.Column(db.String, primary_key=True)
name = db.Column(db.String, default="")
user_id = db.Column(db.String, db.ForeignKey("Users.id"))
user = db.relationship("User", back_populates="books")
API Endpoints
To create Flask API endpoints for these objects, all you have to do is create an API and expose the objects:
def create_api(app, HOST="localhost", PORT=5000, API_PREFIX=""):
api = SAFRSAPI(app, host=HOST, port=PORT, prefix=API_PREFIX)
api.expose_object(User)
api.expose_object(Book)
Flask App
All that is left to do now is creating the Flask app and populate the in-memory sqlite database:
def create_app(config_filename=None, host="localhost"):
app = Flask("demo_app")
app.config.update(SQLALCHEMY_DATABASE_URI="sqlite://")
db.init_app(app)
with app.app_context():
db.create_all()
# Populate the db with users and a books and add the book to the user.books relationship
for i in range(200):
user = User(name=f"user{i}", email=f"email{i}@dev.to")
book = Book(name="test_book")
user.books.append(book)
create_api(app, host)
return app
The API app can be started by calling the flask app.run
:
host = "127.0.0.1" # address where the api will be hosted, change this if you're not running the app on localhost!
app = create_app(host=host)
if __name__ == "__main__":
app.run(host=host)
Dependencies and SQLAlcheymy DB Instance
The app script should start with the imports and SQLAlchemy db:
import sys
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from safrs import SAFRSBase, SAFRSAPI
db = SQLAlchemy()
Running the App
You can start the app from the command line with
python3 demo_devto.py
You can now browse to http://127.0.0.1 to check out the API documentation and use the API. In the swagger UI, you will see the endpoints for the User
and Book
classes:
In the following post I will go into more detail explaining the API functionality and customizations.
Top comments (0)