Skip to content

Instantly share code, notes, and snippets.

@atwalsh
Forked from TonyFrancis/MultiTenantFlask.py
Created October 23, 2017 20:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atwalsh/c9aae9fb0ab078e09da2dd49386eea26 to your computer and use it in GitHub Desktop.
Save atwalsh/c9aae9fb0ab078e09da2dd49386eea26 to your computer and use it in GitHub Desktop.
Creating multi Tenant system with multiple Database. Switching between databases based on subdomain related to tenant
from functools import wraps
from flask import Flask, g, session, request, abort, jsonify
from flask_migrate import MigrateCommand, Migrate
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
flask_app = Flask(__name__, static_folder='./static')
db = SQLAlchemy()
migrate = Migrate()
flask_app.add_url_rule('/static/<path:filename>',
endpoint='static',
subdomain='<tenant>',
view_func=flask_app.send_static_file)
flask_app.config['SERVER_NAME'] = 'localhost:5000'
class Hello(db.Model):
"""
demo Table.
contains name for eg.
"""
__tablename__ = 'hello'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(2000), index=True, nullable=False)
@flask_app.before_request
def start():
"""
Switching DataBase based on subdomain.
This is example multi Tenant with multi DataBase rather than multi schema.
Logic for both is same, before request find the subdomain and
switch its schema or db.
"""
from urlparse import urlparse
subdomain = urlparse(request.url).hostname.split('.')[0]
if subdomain == 'tenant':
flask_app.config.update({
"SQLALCHEMY_DATABASE_URI": 'postgresql://postgres:postgres@localhost/tenant'
})
else:
flask_app.config.update({
"SQLALCHEMY_DATABASE_URI": 'postgresql://postgres:postgres@localhost/tenant2'
})
@flask_app.url_value_preprocessor
def before_route(endpoint, values):
"""Remove tenant from values so it not added all url path."""
if values is not None:
values.pop('tenant', None)
@flask_app.route('/hello', subdomain='<tenant>')
def display_name():
"""Display all object in table hello for each tenant subdomain."""
oHello = Hello.query.all()
return jsonify(tenant=[e.name for e in oHello]), 200
if __name__ == '__main__':
db.init_app(flask_app)
# default db
flask_app.config.update({
"SQLALCHEMY_DATABASE_URI": 'postgresql://postgres:postgres@localhost/tenant2'
})
migrate.init_app(flask_app, db)
manager = Manager(flask_app)
manager.add_command('db', MigrateCommand)
manager.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment