Flask и SQLAlchemy и объект метаданных

это первый раз, когда я использую эту среду.

Та часть SQLAlchemy, которую я хочу использовать, — это только та, которая позволяет мне запрашивать базу данных, используя объекты таблицы с автозагрузкой = True. Я делаю это, поскольку мои таблицы уже существуют в БД (сервер mysql) и не были созданы путем определения моделей фляг.

Я просмотрел всю документацию и, похоже, не нашел ответа. Вот код:

app = Flask(__name__)
app.config.from_object(__name__)

metadata = None

def connect_db():
    engine = create_engine(app.config['DATABASE_URI'])
    global metadata
    metadata = MetaData(bind=engine)
    return engine.connect()


@app.before_request
def before_request():
    g.db = connect_db()


@app.teardown_request
def teardown_request(exception):
    g.db.close()

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

@app.route('/test/<int:id>')
def test(test_result_id):

    testTable = Table('test_table', metadata , autoload=True)

Как видите, мне нужно, чтобы этот объект был глобальным, чтобы получить к нему доступ из функции.

Также я объявляю одну и ту же переменную testTable в каждой функции, которая в ней нуждается. У меня такое чувство, что это не правильный подход. Я не нашел ни одного совета по лучшей практике для такого случая, как мой.

Спасибо всем!


person Riziero    schedule 18.11.2012    source источник


Ответы (1)


Вы видели этот фрагмент? в документах SQLAlchemy?

Возможно, это сработает:

# This is fine as a global global
metadata = MetaData()

@app.before_first_request
def autoload_tables():
    meta.reflect(bind=g.db.bind)

@app.route('/')
def index():
    users_table = meta.tables['users']

Таким образом, ваши таблицы отражаются только один раз для каждого процесса, что, вероятно, вам и нужно. Обратите внимание, что ваш движок также должен быть глобальным, поэтому вам не нужно создавать новый движок в @app.before_request — более подходящим местом является создание приложения.

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

person jd.    schedule 10.12.2012
comment
Вы имели в виду meta = MetaData()? Кроме того, я не уверен, что ссылка на документы SA больше не работает. - person cjauvin; 05.03.2014
comment
Привет, jd. Что, если для какого-то маршрута нам не нужно соединение с БД, то отражение всех таблиц БД для каждого before_request будет избыточным, верно? Как мы могли этого избежать? - person leela; 31.05.2015
comment
Подключение к базе данных должно быть выполнено только один раз, т. е. connect_db() следует вызывать либо при создании экземпляра приложения, либо в обратном вызове before_first_request (не в before_request). Обратите внимание, что отражение в моем ответе происходит только перед первым запросом, а не перед каждым запросом. - person jd.; 01.06.2015