Как избежать жесткого кодирования пути к базе данных с помощью фляги, SQLAlchemy и Declarative_base - PullRequest
0 голосов
/ 24 июня 2018

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

это их база данных.py:

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

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                     autoflush=False,
                                     bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
    # import all modules here that might define models so that
    # they will be registered properly on the metadata.  Otherwise
    # you will have to import them first before calling init_db()
    import yourapplication.models
    Base.metadata.create_all(bind=engine)

Но я не смог выяснить, как избежать жесткого кодирования этого пути БД.

Переменные среды:

Я мог бы просто заменить путь sqlite:///.... на переменную окружения. Но для этого потребуется какой-то способ запустить pytest с одним набором переменных среды, а flask run использовать другой набор. Я бы предпочел, чтобы мои модульные тесты отслеживали их собственную временную базу данных. [2] Мне также хотелось бы, чтобы create_app() создавало приложение Flask, которое выбирало бы путь к базе данных, который является переменной config.

Импорт database.py в контексте приложения

Я думал, что смогу заменить путь к базе данных на current_app.config['DB'] и импортировать базу данных в with app.app_context(). Но классы Model должны импортировать Base, и я не могу создать подкласс Base в контексте приложения. Поэтому, когда модели загружаются, они загружаются вне контекста приложения, и это приводит к ошибкам во время выполнения.

Так, как правильно использовать Declarative_base в приложении фляги с юнит-тестами?

Спасибо за вашу помощь!

[2]: Если это то, что я должен делать, тогда я могу жить с этим. Но кажется, что использование env vars там беспорядочно, когда я настраиваю приложение фляги со своими собственными настройками vars.

1 Ответ

0 голосов
/ 25 июня 2018

Я решил свой вопрос.Вместо того, чтобы использовать фабрику класса Declarative_base:

database.py:

engine="someengine"
db_session=[make a session here]
Base = declarative_base()
Base.query = db_session.query

И имея мои модели импортировать Base,

Я просто следовал шаблону здесь .В файле database.py я создаю немую базу данных с

db = SQLAlchemy()

Затем в init .py на фабрике приложений create_app я могу инициализировать приложение с помощью переменных конфигурации приложения и инициализироватьБД с приложением. *

db.init_app(app)
with app.app_context():
    import site.models
    db.create_all()

Модели наследуются от класса db.Model database.py.

from site.database import db
class MyModel(db.Model)

Я могу получить доступ к базе данных в тестах pytest, обернув тесты в приспособление:

@pytest.fixture
def app():
    app = create_app({[testing config]}
    with app.app_context():
        g.db = db
        yield app
        g.db.session.remove()
        g.db.drop_all()

Это работает для меня сейчас.Тем не менее, если вы думаете, что я делаю что-то не так, дайте мне знать!

* Я думаю, что объект SQLAlchemy, однажды инициализированный с init_app, хранит указатели на значения, которые существуют только при наличии активного контекста приложения.?Это правильно?Вот почему простой вызов db не подключается к базе данных приложений, а вызов db в контексте приложения.

...