Skip to main content

Flask RestPlus SqlAlchemy

Project description

Flask RestPlus SqlAlchemy

Auto generates the Flask RestPlus Model section in swagger from SqlAlchemy models.

Note: Make sure you don't import any endpoints be for you call init_db(flask_application) else the api_model_factory.get_entity will be empty

Disclaimer This project is not at this time, 2020 Feb. 1, affiliated with Flask, Flask-RestPlus or SqlAlchemy projects.

Usage

    from sqlalchemy import BigInteger, Column, Integer, String, DateTime, Date
    from flask_sqlalchemy import SQLAlchemy
    from flask import Flask
    from flask_restplus import Api
    from flask_restplus_sqlalchemy import ApiModelFactory

    flask_app = Flask(__name__) # Flask Application
    flask_app.config['SQLALCHEMY_DATABASE_URI'] = 'connection string'
    # Create RestPlus API
    api: Api = Api(
            version='x',
            title='test_api',
            default='test',
            default_label='test',
            description='Test') # 
    # SQLAlchemy Database instance
    db: SQLAlchemy = SQLAlchemy()

    # normally you would import models here
    # ex: from app.data import models

    # For this example will just make one model
    class Person(db.Model): 
        """ Person Entity
        """
        __tablename__ = "person"
        __abstract__ = False
        id: Column = Column(
            BigInteger().with_variant(Integer, "sqlite"),
            primary_key=True,
            nullable=False
        )
        created_on: Column = Column(DateTime, nullable=False)
        birth: Column = Column(Date, nullable=False)
        first_name: Column = Column(String(100), nullable=False)
        middle_name: Column = Column(String(100), nullable=True)
        last_name: Column = Column(String(100), nullable=False)

    # Bind the SQLAlchemy to the Flask Application
    db.init_app(flask_app)

    # Link Flask Rest Plus API with SQLAlchemy
    api_model_factory = ApiModelFactory(api=api, db=db)

    # Get entity Person 
    model = api_model_factory.get_entity(Person.__tablename__)

Sample Integration into full project

Below is a sample use case.

Folder structure

.
├── sample api
│   ├── api
│   │   ├── auth.py
│   │   ├── endpoints
│   │   │   ├── __init__.py
│   │   │   ├── person.py
│   │   │   └── status.py
│   │   ├── __init__.py
│   │   ├── restplus.py
│   │   └── swagger
│   │       ├── __init__.py
│   │       └── status.py
│   ├── app.py
│   ├── data
│   │   ├── access
│   │   │   ├── dal.py
│   │   │   ├── __init__.py
│   │   │   └── person.py
│   │   ├── __init__.py
│   │   └── models
│   │       ├── audit.py
│   │       ├── __init__.py
│   │       ├── model.py
│   │       └── person.py
│   ├── __init__.py
│   └── settings.py
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── run.py
└── test
    ├── api
    │   All tests should go here
    └── __init__.py

Person Endpoint

This example used A DataAccessLayer as an abstraction, may not needed.

""" Person Endpoint
"""
import logging

from http import HTTPStatus
from flask import request
from flask_restplus import Resource
from ..restplus import api, name_space
from ..swagger import api_model_factory

from ...data.access import DataAccessLayer, PersonDAL
from ..auth import user_id

ENTITY_NAME = 'person'
ENTITY = api_model_factory.get_entity(ENTITY_NAME)
NAME_SPACE = name_space(ENTITY_NAME)


@NAME_SPACE.route('')
class PersonCollection(Resource):
    """ PersonCollection
    """
    log = logging.getLogger(__name__)
    dal: DataAccessLayer = PersonDAL()

    @api.marshal_list_with(ENTITY)
    def get(self):
        """
        Returns list of persons.
        """
        return self.dal.get_collection(), HTTPStatus.OK

    @api.response(HTTPStatus.CREATED, 'Created person')
    @api.expect(ENTITY)
    def post(self):
        """ Creates a new person
        """
        return self.dal.create(user_id(), request.json), HTTPStatus.CREATED


@NAME_SPACE.route('/<int:id>')
@NAME_SPACE.response(404, "Could not find person")
class PersonItem(Resource):
    """ PersonItem
    """
    log = logging.getLogger(__name__)
    dal: DataAccessLayer = PersonDAL()

    @api.marshal_list_with(ENTITY)
    @api.response(HTTPStatus.NOT_FOUND, 'Cant find person')
    def get(self, id: int):
        """ Returns a single person.
        """
        return self.dal.get_item(id), HTTPStatus.OK

    @api.response(HTTPStatus.NO_CONTENT, 'Update classed person information')
    @api.expect(ENTITY)
    def put(self, id):
        """ Updates a person
        """
        self.dal.update(
            user_id=user_id(),
            entity_id=id,
            data=request.json)
        return None, HTTPStatus.NO_CONTENT

    @api.response(HTTPStatus.NO_CONTENT, 'Deleted person information')
    def delete(self, id):
        """ Delete a person
        """
        self.dal.delete(user_id(), id)
        return None, HTTPStatus.NO_CONTENT

Restplus

In above example this is where api and error handling logic is located

""" Api Creation
"""
import logging

from flask_restplus import Api, Namespace
from sqlalchemy.orm.exc import NoResultFound
from .. import __version__
log = logging.getLogger(__name__)

api: Api = Api(
    version=__version__,
    title='My API',
    default='???',
    default_label='',
    description='My Rest Api')


def format_uri(entity_name: str) -> str:
    """ Format url from entity name.
    """
    return entity_name.replace('_', '/')


def explode_entity_name(entity_name: str) -> str:
    """ replaces _ with space
    """
    return entity_name.replace('_', ' ')


def name_space(entity_name) -> Namespace:
    """ Get formatted namespace
    """
    return api.namespace(
        format_uri(entity_name),
        description='Operations related to {}'
        .format(explode_entity_name(entity_name)))


@api.errorhandler
def default_error_handler(e):
    """ By default all errors will be handled here
    """
    message = 'An Unhandled exception has occurred'
    log.exception(e)
    return {'message': message}, 500


@api.errorhandler(NoResultFound)
def database_not_found_error_handler(e):
    """ Database not found
    """
    return {'message': 'A database result was not found'}, 404

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flask_restplus_sqlalchemy-0.0.3.tar.gz (6.5 kB view details)

Uploaded Source

Built Distribution

File details

Details for the file flask_restplus_sqlalchemy-0.0.3.tar.gz.

File metadata

  • Download URL: flask_restplus_sqlalchemy-0.0.3.tar.gz
  • Upload date:
  • Size: 6.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/41.1.0 requests-toolbelt/0.9.1 tqdm/4.42.0 CPython/3.7.5

File hashes

Hashes for flask_restplus_sqlalchemy-0.0.3.tar.gz
Algorithm Hash digest
SHA256 b57867c6b31cb5607fe314f3c8fa0e935826b21cb273f2441a0587b2f90b3a3b
MD5 560de4dfaa7decfe348f908bcff1b647
BLAKE2b-256 e71eda06b65d8d4bafe74867696c1b53a32570a88cff8af0e8986e92ddba27a0

See more details on using hashes here.

File details

Details for the file flask_restplus_sqlalchemy-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: flask_restplus_sqlalchemy-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 7.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/41.1.0 requests-toolbelt/0.9.1 tqdm/4.42.0 CPython/3.7.5

File hashes

Hashes for flask_restplus_sqlalchemy-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 698bcf7155ee6b5840917b84bb43ad73f474eef4d2f8d72bc376772ce09f648e
MD5 04967cab300efcd297da43bae7cae75d
BLAKE2b-256 9ab6a0b73e94485d702de1215e65335ea33892bad39f2a570c0680d28ee64be0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page