2014-02-03 3 views
1

У меня есть веб-приложение, написанное на python с использованием Flask и sqlalchemy. Это приложение работает на Heroku, и как работник я использую расширение металлиста, у меня есть все мои модели, определенные в модели модуля, как это:Использование декларации sqlalchemy во внешнем работнике

from app import db 

class Player(db.Model): 
    __tablename__ = 'players' 
    id = db.Column(db.Integer, primary_key=True) 
    .... 
    type = db.Column(db.String(50)) 

    def __init__(self, ....): 
     .... 

    __mapper_args__ = { 
     'polymorphic_identity':'player', 
     'polymorphic_on':type 
    } 

class Outfielder(Player): 
    __tablename__ = 'outfielders' 
    id = db.Column(db.Integer, db.ForeignKey('players.id'), primary_key=True) 

    __mapper_args__ = { 
     'polymorphic_identity':'outfielder' 
    } 

class Goalkeeper(Player): 
    __tablename__ = 'goalkeepers' 
    id = db.Column(db.Integer, db.ForeignKey('players.id'), primary_key=True) 
    __mapper_args__ = { 
     'polymorphic_identity':'goalkeeper' 
    } 

(Обратите внимание, как этот импорт БД из приложения) я могу создавать экземпляры этих моделей в моем приложении, инстанцировании модели, например, так:

db = SQLAlchemy(app) 

gk = models.Goalkeeper('John', 'Snow', 1, 1, 3456, 67, 55, 187) 
of = models.Outfielder('Gary', 'Lineker', 1, 1, 3999, 77, 78, 176) 

db.session.add(gk) 
db.session.add(of) 
db.session.commit() 

Теперь, что я хотел бы сделать это, чтобы иметь возможность создавать экземпляры этих моделей на мой внешний работника. Единственное, что мешает мне сделать это, - это зависимость от моего модуля приложения. Я не чувствую, что эта зависимость оправдана и хотела бы найти лучший подход к дизайну, чтобы иметь возможность просто экспортировать мой модуль в рабочий экземпляр рабочего и init sqlalchemy и создавать экземпляры моих моделей и сохранять их в базе данных точно так же Точно так же я могу сделать это в самом приложении.

Обратите внимание, что я уже могу получить доступ к своей базе данных от работника, как это:

db = create_engine(db_url) 
metadata = MetaData(db) 

print "connection to the database established" 

players = Table('players', metadata, autoload=True) 
s = players.select() 

Я просто ищу лучший способ отражения моей структуры модели на работнике. В частности, я думаю о сценарии, когда мои модели меняются, и мне придется поддерживать код на обоих концах отдельно. Если мне удастся повторно использовать модели и использовать декларативные на обоих концах, то на стороне рабочего не будет никакого обслуживания, что бы это ни было.

+2

Вероятно, лучший способ определить ваши модели отдельно от Колба-SQLAlchemy и позволяют колбовую SQLAlchemy использовать модели, определенные в отдельном модуле, а не использовать Flask-SQLAlchemy, чтобы вы использовали встроенную базу данных db.Model. К сожалению, дизайн Flask-SQLAlchemy не позволяет этого легко, проблема, которая, мы надеемся, будет рассмотрена в следующей версии (https://github.com/mitsuhiko/flask-sqlalchemy/issues/98). См. [Этот вопрос] (http://stackoverflow.com/questions/19119725/how-to-use-flask-sqlalchemy-with-existing-sqlalchemy-model). –

ответ

4

db.Model является SQLAlchemy declarative_base(), поэтому вы можете использовать свои модели, как и обычные SQLAlchemy.

Этот пример работает (YourModel модель Колба-SQLAlchemy):

from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 

import settings 
from models import YourModel 

engine = create_engine(settings.SQLALCHEMY_DATABASE_URI) 
Session = sessionmaker(bind=engine)  
session = Session() 

# do something with your session 
session.query(YourModel).first() 

Вы должны отвязать db от app, так что вы можете импортировать его, не вызывая app создание, используя db.init_app.

Конечно, вы должны быть здесь осторожны. Если вы загрузите свои настройки динамически, возможно, вы загрузите его с неподходящего места с помощью import settings вместо current_app.config, но похоже, что у вас уже есть ваш рабочий, и это не проблема для вас.

Другой вариант - создать еще одно приложение Flask вместо огромного веб-приложения.

Из Колба-SQLAlchemy документы (http://pythonhosted.org/Flask-SQLAlchemy/api.html#flask.ext.sqlalchemy.SQLAlchemy):

Вы все еще можете использовать SQLAlchemy и sqlalchemy.orm непосредственно, но обратите внимание, что Колба-SQLAlchemy настройки доступны только через экземпляр этого класса SQLAlchemy. В классах запросов по умолчанию используется BaseQuery для db.Query, db.Model.query_class и default_class для db.relationship и db.backref. Если вы используете эти интерфейсы через sqlalchemy и sqlalchemy.orm непосредственно, класс запросов по умолчанию будет быть в sqlalchemy.

EDIT: Еще одна вещь, чтобы помнить при смешивании SQLAlchemy сессии с моделями колба-SQLAlchemy, что колба-SQLAlchemy объект сеанса на самом деле подкласс, с добавлением словаря _model_changes. Согласно this answer, вы не сможете совершить сеанс, если вы не добавить поле _model_changes:

def create_session(config): 
    engine = create_engine(config['DATABASE_URI']) 
    Session = sessionmaker(bind=engine) 
    session = Session() 
    session._model_changes = {} 
    return session 
+0

Работает как очарование, спасибо. Я позволил себе отредактировать ваш ответ с какой-то важной информацией, потому что в пути был один путь. – lawicko

+0

Я не тестировал фиксацию. Спасибо за обновление. Похож на ошибку Flask-SQLAlchemy. – iurisilvio

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