Program Club

Flask 모델을 분산시킬 때 RuntimeError : 'application not registered on db'가 발생했습니다.

proclub 2020. 11. 23. 20:22
반응형

Flask 모델을 분산시킬 때 RuntimeError : 'application not registered on db'가 발생했습니다.


모델, 청사진을 분산시켜 내 Flask 애플리케이션을 리팩토링하고 있지만 런타임 오류가 있습니다.

def create_app():
    app = flask.Flask("app")
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
    app.register_blueprint(api)
    db.init_app(app)
    db.create_all()
    return app

다음 문제가 있습니다 (샘플 프로젝트는 여기에서 호스팅됩니다 : https://github.com/chfw/sample ).

Traceback (most recent call last):
  File "application.py", line 17, in <module>
    app = create_app()
  File "application.py", line 12, in create_app
    db.create_all()
  File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 856, in create_all
    self._execute_for_all_tables(app, bind, 'create_all')
  File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 836, in _execute_for_all_tables
    app = self.get_app(app)
  File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 809, in get_app
    raise RuntimeError('application not registered on db 
           'RuntimeError: application not registered on db 
            instance and no application bound to current context

이 주제에 대해 조사했습니다. 리팩토링은 여기에 제안됩니다.

Flask-SQLAlchemy 가져 오기 / 컨텍스트 문제

여기서도 동일한 문제가 발생했습니다.

http://flask.pocoo.org/mailinglist/archive/2010/8/30/sqlalchemy-init-app-problem/#b1c3beb68573efef4d6e571ebc68fa0b

그리고 위의 스레드 (2010)는 다음과 같은 해킹을 제안했습니다.

    app.register_blueprint(api)
    db.app=app #<------------<<
    db.init_app(app)

이 작업을 올바르게 수행하는 방법을 아는 사람이 있습니까? 어떻게 해결 했나요?

감사


이것은 Flask의 애플리케이션 컨텍스트관련이 있습니다. 으로 초기화 db.init_app(app)되면 Flask-SQLAlchemy는 어떤 앱이 "현재"앱인지 알지 못합니다 (Flask는 동일한 인터프리터에서 여러 앱허용 함을 기억하십시오 ). SQLAlchemy동일한 프로세스에서 동일한 인스턴스를 사용하는 여러 앱을 가질 수 있으며 Flask-SQLAlchemy는 모든 것이 Flask의 컨텍스트 로컬 특성 으로 인해 어떤 것이 "현재"인지 알아야 합니다.

런타임 중에이 작업을 수행해야하는 경우 모든 호출에 대해 어떤 앱이 "현재"앱인지 명시 적으로 지정해야합니다. with app.app_context()블록 을 사용하도록 코드를 변경하면 됩니다.

def create_app():
    app = flask.Flask("app")
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
    app.register_blueprint(api)
    db.init_app(app)
    with app.app_context():
        # Extensions like Flask-SQLAlchemy now know what the "current" app
        # is while within this block. Therefore, you can now run........
        db.create_all()

    return app

If you are writing a standalone script that needs the app context, you can push the context at the beginning rather than putting everything in a with block.

create_app().app_context().push()

If you write a command for Flask's cli the command will automatically have access to the context.


Mark's answer was great and it helped me a lot. However, another way to approach this is to run the code that relies on the app context in a function decorated with @app.before_first_request. See http://flask.pocoo.org/docs/0.10/appcontext/ for more information. That's in fact how I ended up doing it, largely because I wanted to be able to call the initialization code outside of flask as well, which I handle this way.

In my case I want to be able to test SQLAlchemy models as plain SQLAlchemy models without Flask-SQLAlchemy, though the db in the code below is simply a (Flask) SQLAlchemy db.

@app.before_first_request
def recreate_test_databases(engine = None, session = None):
  if engine == None:
    engine = db.engine
  if session == None:
    session = db.session

  Base.metadata.drop_all(bind=engine)
  Base.metadata.create_all(bind=engine)
  # Additional setup code

참고URL : https://stackoverflow.com/questions/19437883/when-scattering-flask-models-runtimeerror-application-not-registered-on-db-w

반응형