Customizing SlashDB API with declarative models
You can easily modify your API with custom SQLalchemy models and a mixin class provided by the SlashDB team.
All you need is to declare your models and wrap them into a setuptools compatible module.
How it works
SlashDB loads manually defined model if database configuration has attribute autoload: false. Otherwise SlashDB reflects database by itself. This is defined in GUI /dbdef or in the backend in file /etc/slashdb/databases.cfg
MyThings:
  alternate_key: {}
  autoload: false
  autoload_user: {dbuser: someUser, dbpass: somePassword}
  connect_status: Disconnected
  connection: /somepath/mythings.sqlite
  creator: admin
  db_encoding: utf-8
  db_id: MyThings
  db_schema: null
  db_type: sqlite
  desc: 'Sample database of my things'
  excluded_columns: {}
  execute: []
  foreign_keys: {}
  autoconnect: false
  owners: [admin]
  read: []
  write: []
When loading manually defined models SlashDB iterates through group of entry points named 'sqlalchemy_sdb_module'. Then looks for an entry point which, name matches the Database ID (in below example it's "MyThings") and executes a function attached to the entry point. This function takes the Database ID, database config object and the initial settings object, returning a list of model classes that represent the database.
Creating your own plugin for SlashDB
Basic plugin example
mypluginroot
    car_db
    └── __init__.py
    setup.py
Important: The module name should reflect the actual Database ID used in SlashDB-s configuration.
cat custom_models/__init__.py
import sys
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from slashdb.models.sqlalchemy_sdb import Model
Base = declarative_base()
class Brand(Base, Model):
    u"""Simple declarative-style SQLAlchemy model."""
    __tablename__ = 'brands'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    cars = relationship('Car', backref='brand')
class Car(Base, Model):
    u"""Simple declarative-style SQLAlchemy model - with relations."""
    __tablename__ = 'cars'
    id = Column(Integer, primary_key=True)
    brand_id = Column(Integer, ForeignKey('brands.id'))
def get_models(db_id, db_config, ini_settings):
    """Returns list of database model classes for certain database.
    :param db_id: Database id which SlashDB is configuring.
    :param db_config: Database config detail object.
    :param db_config: Parsed *.ini file used to setup SlashDB.
    """
    # registration of classes is deferred
    # pick from the above classes the ones to expose
    return (Brand, Car)
setup
cat setup.py
#!/usr/bin/env python
from setuptools import setup
VERSION = '0.0.1'
setup(
    name='cardbplugin',
    version=VERSION,
    license='',
    description='My car database plugin for SlashDB',
    author='VTE',
    author_email='',
    url='',
    download_url='',
    keywords='cars database plugin slashdb',
    classifiers=[],
    platforms='All',
    install_requires=['slashdb>=0.9.0'],
    packages=['car_db'],
    entry_points={
        'sqlalchemy_sdb_module': ['CarDB=car_db:get_models']
    },
    zip_safe=False,
    tests_require=['nose >= 0.11'],
)
Installing your plugin
while in mypluginroot do:
(sudo) python setup.py install
Example API customizations using models
Adding new tables with relations
from slashdb.models.sqlalchemy_sdb import Model
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
class Thing(Base, Model):
    u"""Simple declarative-style SQLAlchemy model."""
    __tablename__ = 'things'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    otherthings = relationship('OtherThing', back_populates='thing')
class OtherThing(Base, Model):
    u"""Other simple declarative-style SQLAlchemy model - with relations to Thing."""
    __tablename__ = 'otherthings'
    id = Column(Integer, primary_key=True)
    thing_id = Column(Integer, ForeignKey('things.id'))
    thing = relationship('Thing', back_populates='otherthings')
Hiding columns on an existing table
from slashdb.models.sqlalchemy_sdb import Model
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine('sqlite:///path/to/your/Chinook.sqlite'
class EmployeeWithHiddenFields(Base, Model):
    u"""Show only 'EmployeeId', 'FirstName', 'ReportsTo' columns."""
    __table__ = Table(
        'Employee', Base.metadata, include_columns=('EmployeeId', 'FirstName', 'ReportsTo'),
        autoload=True, autoload_with=engine, schema=Base.metadata.schema
    )
    __tablename__ = 'Employee'
Change how your SlashDB API displays column names in your custom models
from slashdb.models.sqlalchemy_sdb import Model
from sqlalchemy import Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class AwesomeDeclarativeArtist(Base, Model):
    u"""A declarative model with aliased column names."""
    __tablename__ = 'awesome_artist'
    artist_ID = Column('id', Integer, primary_key=True)
    ArtistName = Column('artist_name', Unicode(120))
and the resulting example JSON output:
curl http://myslashdb/db/SQLiteChinook/AwesomeDeclarativeArtist.json
// id -> artist_ID
// artist_name -> artist_name
[
    {
        'artist_ID': 1,
        'ArtistName': 'Some Artist',
        '__href': '/db/test/AwesomeDeclarativeArtist/artist_ID/1.json'
    }
]
Change how your SlashDB API displays column names in existing tables
from slashdb.models.sqlalchemy_sdb import Model
from sqlalchemy import Integer, Text, create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine('sqlite:///path/to/your/Chinook.sqlite')
class ArtistWithAliasedColumns(Base, Model):
    u"""Show only 'ArtistId', 'Name' and do some aliasing."""
    __tablename__ = 'Artist'
    __table_args__ = {
        'include_columns': ('ArtistId', 'Name'), 'extend_existing': True,
        'autoload': True, 'autoload_with': engine, 'schema': Base.metadata.schema
    }
    artist_id = Column('ArtistId', Integer, primary_key=True)
    artist_name = Column('Name', Text)
and the resulting example JSON output:
curl http://myslashdb/db/SQLiteChinook/ArtistWithAliasedColumns/artist_id/1..3.json
// ArtistId -> artist_id
// Name -> artist_name
[
    {
        'artist_id': 1,
        'artist_name': 'AC/DC',
        '__href': '/db/test/ArtistWithAliasedColumns/artist_id/1.json'
    },
    {
        'artist_id': 2,
        'artist_name': 'Accept',
        '__href': '/db/test/ArtistWithAliasedColumns/artist_id/2.json'
    },
    {
        'artist_id': 3,
        'artist_name': 'Aerosmith',
        '__href': '/db/test/ArtistWithAliasedColumns/artist_id/3.json'
    }
]