2011-04-25 2 views
5

Допустим, у меня есть часть моего приложения Flask, которое я хочу вытащить и использовать в нескольких разных проектах. Он имеет модели SQLAlchemy с использованием Flask-SQLAlchemy, а также представления и шаблоны. Я могу получить декораторы app.route с помощью модуля, но как я могу обработать объект SQLAlchemy db?Как сделать повторно используемый компонент с Flask-SQLAlchemy?

Поскольку мой компонент должен быть отдельным, я не могу просто импортировать объект db. Но я не думаю, что я должен дважды создать объект db. Как бы я мог смешивать свои метаданные с метаданными в остальной части проекта?

ответ

3

Сначала вы должны поделиться metadata и не использовать flask-sqlalchemy db.Model в качестве базы для повторного использования приложения.

Во-вторых, вы должны воссоздать все классы с расширением их новых баз из фляжки-sqlalchemy для поддержки сигналов, коротких сокращений и других вещей.

Интеграция баз (это может быть ошибка):

def integrate_models(cls, nbase): 
     new_bases = list(cls.__bases__) + [nbase] 
     new_dict = dict(cls.__dict__) 
     new_dict.update(dict(nbase.__dict__)) 
     return type.__new__(cls.__class__, cls.__name__, tuple(new_bases), new_dict) 

Пример Колба приложение с расширением SQLAlchemy:

# -*- coding: utf-8 -*- 
from flask import Flask 
from flaskext.sqlalchemy import SQLAlchemy 

app = Flask(__name__) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' 
db = SQLAlchemy(app) 

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 
    email = db.Column(db.String(120), unique=True) 

    def __init__(self, username, email): 
     self.username = username 
     self.email = email 

    def __repr__(self): 
     return '<User %r>' % self.username 

if __name__ == '__main__': 
     from some_model_base import init_metadata 
     init_metadata(db.Model.metadata) 

     from some_model import SomeClass 

     SomeClass = integrate_models(SomeClass, db.Model) 

     db.create_all() 

     print SomeClass.query.all() 

Где some_model_base.py:

from sqlalchemy.ext.declarative import declarative_base 
Base = declarative_base() 

def init_metadata(metadata): 
    Base.metadata = metadata 

И some_model.py :

from sqlalchemy import Column, Integer, String 
from some_model_base import Base 

class SomeClass(Base): 
    __tablename__ = 'some_table' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(50)) 

В этом примере проверена только ярлык db.create_all и SomeClass.query.

Извините за мой плохой английский.

+0

Хм, мне нужно попробовать это. Можете ли вы найти способ настроить модели в другом модуле, чтобы иметь отношения с моделями в основной программе? –

+0

Я думаю, что лучший способ сделать это - объявить в своих повторно используемых базовых классах приложений или MixIns, а затем собрать конкретные модели, подклассифицирующие их. – estin

1

Вы должны использовать flask.current_app, это прокси-объект для доступа к текущему приложению, и это то, что используется в некоторых расширениях. Таким образом, ваш код будет выглядеть примерно так:

from flask import current_app 
from flaskext.sqlalchemy import SQLAlchemy 

db = SQLAlchemy(current_app) 

, а затем использовать db объект, как вы обычно делаете. Но я не уверен, что это сработает, если пользователь будет использовать ваш модуль, а также должен будет использовать flaskext.sqlalchemy, возможно, это противоречило бы, я бы предложил протестировать это, чтобы убедиться, что ваш модуль будет на 100% совместим с любым приложением flask ,

Смежные вопросы