2015-04-15 21 views
13

Mam „wielu dzierżawcówKolba aplikację internetową, która graniczy z 1 „Master” bazy danych MySQL (używane do wyszukiwania informacji o kliencie) i dziesiątki baz danych MySQL "klienta" (wszystkie mają ten sam schemat).Dynamicznie ustawienie połączenia z bazą danych Kolba-SQLAlchemy w multi-tenant app

Obecnie próbuję użyć SQLAlchemy wraz z rozszerzeniem Kolba-sqlalchemy do współpracy z bazami danych, ale jestem stara się znaleźć sposób, aby umożliwić modele zdefiniować w mojej aplikacji do dynamicznie przełączaj kontekst z jednej bazy danych klienta na inną, w zależności od klienta.

Na Flask-SQLAlchemy site, prosty przykład pokazane wzdłuż linii:

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 

app = Flask(__name__) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:[email protected]/db1' 
db = SQLAlchemy(app) 

class User(db.Model): 
    # Etc. 

Jedynym problemem jest konfiguracja SQLALCHEMY_DATABASE_URI odbywa się statycznie. Być może będę musiał przełączać się pomiędzy mysql://username:[email protected]/db1 i mysql://username:[email protected]/db1 (lub dowolnym innym dowolnym URI MySQL), w zależności od tego, który klient wysyła żądanie.

Znalazłem kilka podobnych pytań (patrz poniżej), ale muszę jeszcze wymyślić czysty sposób, aby to zrobić, szczególnie w przypadku korzystania z rozszerzenia Flask-SQLAlchemy.

With sqlalchemy how to dynamically bind to database engine on a per-request basis

Flask SQLAlchemy setup dynamic URI

Ja również widziałem kilka przykładów, które zostały przewidziane do obsługi sharded baz danych (które powinny mieć zastosowanie, jak również, jako bazy danych są zasadniczo sharded logicznie przez klienta), ale, znowu, nic specyficznego dla Flask-SQLAlchemy.

Jeśli ma sens, Jestem również otwarty na używanie SQLAlchemy bezpośrednio, bez rozszerzenia Flask-SQLAlchemy. Jestem nowy w SQLAlchemy - każda pomoc będzie bardzo ceniona!

Edytuj: Możliwość odzwierciedlenia schematów tabel z bazy danych byłaby dodatkowym atutem.

+0

Czy widziałeś http://stackoverflow.com/questions/7923966/flask-sqlalchemy-with-dynamic-database-connections i jeśli tak, to jakie dalsze pytania masz? –

+2

@SeanVieira Dzięki - Właśnie sprawdziłem tę odpowiedź i wydaje się to mieć sens.Zastanawiam się nad utworzeniem sesji na żądanie i przechowywaniem w 'flask.g'. Jestem w większości zakłopotany, jak ustawić samą klasę. W tym przykładzie 'User' jest podklasą' db.Model', a 'db' jest inicjowana z' SQLALCHEMYY_DATABASE_URI'. Czy posiadanie 'User' dziedziczy z klasy bazowej utworzonej za pomocą' sqlalchemy.ext.declarative.declarative_base() 'również działa, czy jest tam inna klasa, której mogę użyć zamiast' db.Model' Flask-SQLAlchemy, która nie jest zależna od na konkretnej konfiguracji bazy danych? – jstol

+0

Przeczytaj to: http://flask-sqlalchemy.pocoo.org/2.1/binds/, a następnie sprawdź to: https://gist.github.com/adhorn/b84dc47175259992d406. – ramabodhi

Odpowiedz

0

Możesz zrobić coś takiego. FYI to czysta SQLAlchemy, a nie Flask-SQLAlchemy. Mam nadzieję, że potrzebujesz tego do materiałów tylko do odczytu. Można wymyślić jakieś inne rzeczy, aby napisać rzeczy, jak nawet słuchaczy na sesji/modele

from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 

# an Engine, which the Session will use for connection 
# resources 
some_engine_1 = create_engine('postgresql://scott:[email protected]/') 
some_engine_2 = create_engine('postgresql://adriel:[email protected]/') 

# create a configured "Session" class 
Session_1 = sessionmaker(bind=some_engine_1) 
Session_2 = sessionmaker(bind=some_engine_2) 

# create a Session 
session_1 = Session_1() 
session_2 = Session_2() 

Base = declarative_base() 

class ModelBase(Base): 
    #different custom queries for each database 
    master_query = session_1.query_property() 
    client_1_query = session_2.query_property() 


class User(ModelBase): 
    pass 
    #ETC 


##Accessing the different databases: 
User.master_query.filter(User.id == 1).all() 
User.client_1_query.filter(User.id == 1).all() 
2

Jeśli używasz kolba-sqlalchemy 0.12 lub nowszej, funkcja ta jest obsługiwana wiąże.

SQLALCHEMY_DATABASE_URI = 'postgres://localhost/main' 
SQLALCHEMY_BINDS = { 
'users':  'mysqldb://localhost/users', 
'appmeta':  'sqlite:////path/to/appmeta.db' 
} 

I można określić bazę danych połączeń w definicji modelu.

class User(db.Model): 
    __bind_key__ = 'users' 
    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 

Będzie używać mysqldb auto. Aby uzyskać więcej informacji, możesz odnieść się do oficjalnego dokumentu. Multiple Databases with Binds

+0

jest to właściwa odpowiedź do partycjonowania pionowego, ale nie sądzę, że można to zrobić w poziomie. to znaczy, jeśli mam kolumnę 'client_id' na wszystkich moich tabelach i chcę mieć wszystko z liczbami nieparzystymi na jednym pudełku i wszystko z wartościami równymi na drugim, nie sądzę, aby powiązania działały. Potrzebuję sqlalchemy.ext.horizontal_shard.ShardedSession –

Powiązane problemy