Отражение различных баз данных в заводских настройках Flask - PullRequest
1 голос
/ 04 июля 2019

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

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

Я пробовал разные варианты передачи приложения через current_app в мой models.py, но ничегоработал.

config.py:

class Config(object):

    #Secret key
    SECRET_KEY = 'my_very_secret_key'

    ITEMS_PER_PAGE = 25

    SQLALCHEMY_BINDS = {
        'mysql_bind': 'mysql+mysqlconnector://localhost:3306/tmpdb'
    }
    SQLALCHEMY_TRACK_MODIFICATIONS = False

main.py:

from webapp import create_app

app = create_app('config.Config')

if __name__ == '__main__':
    app.run(debug=true)

webapp / init .py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config_object):
    app=Flask(__name__)
    app.config.from_object(config_object)

    db.init_app(app)

    from main import create_module as main_create_module
    main_create_module(app)

    return app

webapp / main / init .py:

def create_module(app):
    from .controller import blueprint
    app.register(blueprint)

webapp / main / controller.py:

from flask import Blueprint, render_template, current_app as app
from .models import db, MyTable # <-- Problem might be here ...

bluerint = Blueprint('main', __name__)

@blueprint.route('/'):
def index():
    resp = db.session.query(MyTable)\
            .db.func.count(MyTable.versions)\
            .filter(MyTable.versions =! '')\
            .group_by(MyTable.name).all()
    if resp:
        return render_template('index.html', respo=respo)
    else:
        return 'Nothing happend'

webapp / main /models.py:

from .. import db # <-- and here ...

db.reflect(bind='mysql_bind')

class MyTable(db.Model):
    __bind_key__ = 'mysql_bind'
    __table__ = db.metadata.tables['my_table']

Ожидаемый результат - заставить отражение работать в разных чертежах.

Ответы [ 2 ]

2 голосов
/ 04 июля 2019

Получилось, полное решение здесь: https://github.com/researcher2/stackoverflow_56885380

Я использовал sqllite3 для теста, запустите скрипт create_db.py, чтобы настроить db. Запустите колбу с debug.sh, так как в последних версиях вы больше не можете просто использовать app.run () внутри __main__.

Объяснение

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

Объект БД не связан с планом, он связан с приложением, которое предоставляет информацию о конфигурации. Оказавшись внутри представлений чертежей, вы получите доступ к объекту db с соответствующим контекстом приложения, доступным автоматически. Что касается db.reflect, вам нужно сделать вызов внутри create_app и передать ему объект приложения (предпочтительно) или импортировать приложение внутри модели, которая является спагетти.

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

Таким образом, ваши чертежи будут иметь доступ ко всем импортированным таблицам, а flask-sqlalchemy знает, какое соединение с БД использовать, основываясь на привязке.

Обычно я фанат явного определения таблиц, поэтому у вас есть доступ к объектам и полям ORM при завершении кода. У вас есть много таблиц / полей или, может быть, вы создаете что-то для запроса метаданных таблицы для полной автоматизации в любой схеме? Например, просмотрщик схем или что-то в этом роде.

Это может быть полезно для других, приходящих на этот пост: https://flask -sqlalchemy.palletsprojects.com / ен / 2.x / контексты /

1 голос
/ 05 июля 2019

Brilliant!Большое спасибо.Получил это также работает.Ваш совет дал мне подсказку, чтобы найти другой путь:

@blueprint.route('/')
def index():

    # pushing app_context() to import MyTable
    # now I can use db.reflect() also in models.py
    with app.app_context():
        from .models import MyTable

    results = db.session.query(MyTable).all()
    print(results)
    for row in results:
        print (row)
        print(row.versions)
        print(row.name)

    if results:
        return render_template('my_table.html', results=results)
    else:
        return 'Nothing happend'

Тогда отражение можно сделать внутри models.py.Ссылка, которую вы разместили, действительно полезна, не знаю, почему я сама не споткнулась об этом ...

Во всяком случае, у меня сейчас гораздо больше возможностей, чем раньше!

Ура,спариваться!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...