Ошибка преобразования базы данных sqllite в базу данных postgresql при развертывании приложения Flask в Heroku - PullRequest
0 голосов
/ 06 марта 2020

Мое flask приложение, развернутое с Heroku, аварийно завершает работу, когда я изменяю базу данных на postgresql с sqllite.

Я настроил свое приложение flask, используя базу данных SQL Lite для локальной разработки. Первоначально мой DATABASE_URI в моем конфигурационном файле был следующим:

SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(basedir, "app.db")

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

Я добавил postgresql в Heroku и проверил URL, выполнив os.environ.get ('DATABASE_URL') в терминале Heroku Python. Я изменил свой DATABASE_URI на:

 SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or "sqlite:///" + os.path.join(basedir, "app.db") 

Теперь при развертывании в Heroku выдается ошибка.

    2020-03-06T15:54:29.068483+00:00 app[web.1]: LINE 1: PRAGMA foreign_keys=ON
    2020-03-06T15:54:29.068484+00:00 app[web.1]: ^
    2020-03-06T15:54:29.068484+00:00 app[web.1]:
    2020-03-06T15:54:29.068484+00:00 app[web.1]:
    2020-03-06T15:54:29.068485+00:00 app[web.1]: The above exception
    was the direct cause of the following exception:

  2020-03-06T16:01:19.714003+00:00 app[web.1]: pool.dispatch.connect(self.connection, self)
    2020-03-06T16:01:19.714004+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/event/attr.py", line 320, in __call__
    2020-03-06T16:01:19.714004+00:00 app[web.1]: fn(*args, **kw)
    2020-03-06T16:01:19.714005+00:00 app[web.1]: File "/app/app/__init__.py", line 47, in set_sqlite_pragma
    2020-03-06T16:01:19.714005+00:00 app[web.1]: cursor.execute("PRAGMA foreign_keys=ON")
    2020-03-06T16:01:19.714006+00:00 app[web.1]: sqlalchemy.exc.ProgrammingError: (psycopg2.errors.SyntaxError) syntax error at or near "PRAGMA"
    2020-03-06T16:01:19.714006+00:00 app[web.1]: LINE 1: PRAGMA foreign_keys=ON
    2020-03-06T16:01:19.714006+00:00 app[web.1]: ^
    2020-03-06T16:01:19.714007+00:00 app[web.1]:
    2020-03-06T16:01:19.714007+00:00 app[web.1]: (Background on this
    error at: http://sqlalche.me/e/f405)
    2020-03-06T16:01:19.714912+00:00 app[web.1]: [2020-03-06 16:01:19 +0000] [16] [INFO] Worker exiting (pid: 16)
    2020-03-06T16:01:19.853253+00:00 app[web.1]: [2020-03-06 16:01:19 +0000] [12] [INFO] Shutting down: Master
    2020-03-06T16:01:19.853442+00:00 app[web.1]: [2020-03-06 16:01:19 +0000] [12] [INFO] Reason: Worker failed to boot.
    2020-03-06T16:01:19.958297+00:00 heroku[web.1]: State changed from up to crashed
    2020-03-06T16:01:19.940169+00:00 heroku[web.1]: Process exited with status 3

Вот мой полный config.py

import os
from dotenv import load_dotenv

basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))

class Config(object):    
    CSRF_ENABLED = True
    SECRET_KEY = "youwillneverguess"

    OPENID_PROVIDERS = [
        {"name": "Google", "url": "https://www.google.com/accounts/o8/id"},
        {"name": "Yahoo", "url": "https://me.yahoo.com"},
        {"name": "AOL", "url": "http://openid.aol.com/<username>"},
        {"name": "Flickr", "url": "http://www.flickr.com/<username>"},
        {"name": "MyOpenID", "url": "https://www.myopenid.com"},
    ]

    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or "sqlite:///" + os.path.join(basedir, "app.db")
    #SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(basedir, "app.db")
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    BABEL_DEFAULT_LOCALE = "en"
    BABEL_DEFAULT_FOLDER = "translations"
    LANGUAGES = {
        "en": {"flag": "gb", "name": "English"},
        "pt": {"flag": "pt", "name": "Portuguese"},
        "es": {"flag": "es", "name": "Spanish"},
        "de": {"flag": "de", "name": "German"},
        "zh": {"flag": "cn", "name": "Chinese"},
        "ru": {"flag": "ru", "name": "Russian"},
    }

    # ------------------------------
    # GLOBALS FOR GENERAL APP's
    # ------------------------------
    UPLOAD_FOLDER = basedir + "/app/static/uploads/"
    IMG_UPLOAD_FOLDER = basedir + "/app/static/uploads/"
    IMG_UPLOAD_URL = "/static/uploads/"
    IMG_SIZE = (150, 150, True)
    AUTH_TYPE = 1
    AUTH_ROLE_ADMIN = "Admin"
    AUTH_ROLE_PUBLIC = "Public"
    APP_NAME = "Emily’s MDL1 Class"
    # APP_THEME = ""  # default
    # APP_THEME = "cerulean.css"      # COOL
    # APP_THEME = "cerulean.css"      # COOL
    # APP_THEME = "amelia.css"
    # APP_THEME = "cosmo.css"
    # APP_THEME = "cyborg.css"       # COOL
    APP_THEME = "flatly.css"
    # APP_THEME = "journal.css"
    # APP_THEME = "readable.css"
    # APP_THEME = "simplex.css"
    # APP_THEME = "slate.css"          # COOL
    # APP_THEME = "spacelab.css"      # NICE
    # APP_THEME = "united.css"

    # ----------------------------
    FAB_ROLES = {
        "ReadOnly": [
            ["DoctorModelView", "can_list"],
            ["DoctorModelView", "can_show"],
            ["back", "can_show"],
            ["DoctorModelView", "menu_access"],
            ["DoctorModelView", "can_get"],
            ["DoctorModelView", "can_info"],
            ["UserDBModelView", "can_list"],
            ["UserDBModelView", "can_show"],
            ["UserDBModelView", "menu_access"],
            ["UserDBModelView", "can_get"],
            ["UserDBModelView", "can_info"],
            ["UserDBModelView", "can_info"]
        ]
    }
    LOG_TO_STDOUT = os.environ.get('LOG_TO_STDOUT')

и мой init .py

import logging
import os
from config import Config
from flask_migrate import Migrate
from flask import Flask, request, current_app
from flask_appbuilder import AppBuilder, SQLA
from sqlalchemy import event
from sqlalchemy.engine import Engine
from app.index import MyIndexView
from logging.handlers import SMTPHandler, RotatingFileHandler



app = Flask(__name__)
app.config.from_object(Config)
db = SQLA(app)
appbuilder = AppBuilder(app, db.session, indexview=MyIndexView, base_template='mybase.html')
migrate = Migrate(app, db)

if not app.debug and not app.testing:
        if app.config['LOG_TO_STDOUT']:
            stream_handler = logging.StreamHandler()
            stream_handler.setLevel(logging.INFO)
            app.logger.addHandler(stream_handler)
        else:
            if not os.path.exists('logs'):
                os.mkdir('logs')
            file_handler = RotatingFileHandler('logs/microblog.log',
                                               maxBytes=10240, backupCount=10)
            file_handler.setFormatter(logging.Formatter(
                '%(asctime)s %(levelname)s: %(message)s '
                '[in %(pathname)s:%(lineno)d]'))
            file_handler.setLevel(logging.INFO)
            app.logger.addHandler(file_handler)

        app.logger.setLevel(logging.INFO)
        app.logger.info('Database startup')

logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
logging.getLogger().setLevel(logging.DEBUG)



@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()


from . import views, models  # noqa

и мои требования.txt

alembic==1.4.1
apispec==1.3.3
attrs==19.3.0
Babel==2.8.0
Click==7.0
colorama==0.4.3
defusedxml==0.6.0
Flask==1.1.1
Flask-AppBuilder==2.2.4
Flask-Babel==1.0.0
Flask-JWT-Extended==3.24.1
Flask-Login==0.4.1
Flask-Migrate==2.5.2
Flask-OpenID==1.2.5
Flask-SQLAlchemy==2.4.1
Flask-WTF==0.14.3
gunicorn==20.0.4
importlib-metadata==1.5.0
itsdangerous==1.1.0
Jinja2==2.11.1
jsonschema==3.2.0
Mako==1.1.2
MarkupSafe==1.1.1
marshmallow==2.19.5
marshmallow-enum==1.5.1
marshmallow-sqlalchemy==0.22.3
Pillow==7.0.0
prison==0.1.2
psycopg2==2.8.4
PyJWT==1.7.1
pyrsistent==0.15.7
python-dateutil==2.8.1
python-dotenv==0.12.0
python-editor==1.0.4
python3-openid==3.1.0
pytz==2019.3
PyYAML==5.3
six==1.14.0
SQLAlchemy==1.3.13
SQLAlchemy-Utils==0.36.1
Werkzeug==1.0.0
WTForms==2.2.1
zipp==3.1.0

и мой Procfile для развертывания в Heroku

web: flask db upgrade; gunicorn app:app

1 Ответ

0 голосов
/ 06 марта 2020

Избавился от

@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...