-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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