Gitau Harrison
Gitau Harrison

Reputation: 3517

PostgreSQL Tables not updated in Heroku Deployment using Python and Flask

I have successfully deployed an app in Heroku I built using Python and Flask. Locally, user registration and authentication works as expected. However, when I try to sign up or even log in to the deployed app, heroku logs --tail shows this error:

sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedTable) relation "user" does not exist
2020-10-04T05:30:18.432952+00:00 app[web.1]: LINE 2: FROM "user"
2020-10-04T05:30:18.432952+00:00 app[web.1]: ^
2020-10-04T05:30:18.432953+00:00 app[web.1]: 
2020-10-04T05:30:18.432953+00:00 app[web.1]: [SQL: SELECT "user".id AS user_id, "user".username AS user_username, "user".email AS user_email, "user".password_hash AS user_password_hash, "user".about_me AS user_about_me, "user".last_seen AS user_last_seen
2020-10-04T05:30:18.432954+00:00 app[web.1]: FROM "user"
2020-10-04T05:30:18.432954+00:00 app[web.1]: WHERE "user".username = %(username_1)s
2020-10-04T05:30:18.432954+00:00 app[web.1]: LIMIT %(param_1)s]
2020-10-04T05:30:18.432955+00:00 app[web.1]: [parameters: {'username_1': 'harry', 'param_1': 1}]
2020-10-04T05:30:18.432960+00:00 app[web.1]: (Background on this error at: http://sqlalche.me/e/f405)

So, I looked at the status of my database and noted that the tables in my db (I have user and posts) is not updated. I had run:

$ heroku pg:info DATABASE

=== DATABASE_URL
Plan:                  Hobby-dev
Status:                Available
Connections:           1/20
PG Version:            12.4
Created:               2020-10-05 01:07 UTC
Data Size:             7.9 MB
Tables:                0
Rows:                  0/10000 (In compliance)
Fork/Follow:           Unsupported
Rollback:              Unsupported
Continuous Protection: Off
Add-on:                postgresql-solid-77130

My local database is SQLite which saves data on my local disk. I switched to PostgreSQL as recommended my Heroku by getting an addon and successufully created a DATABASE_URL. I can confirm the database URL when I compare my terminal result from:

$ heroku config:get DATABASE_URL

with that in the addon overview on Heroku dashboard. At this point, I have the DATABASE_URL. To update my db, I run:

$ heroku run flask db upgrade

This should update my tables, but it does not. Instead I get the error:

Traceback (most recent call last):
  File "/app/.heroku/python/bin/flask", line 8, in <module>
    sys.exit(main())
  File "/app/.heroku/python/lib/python3.6/site-packages/flask/cli.py", line 967, in main
    cli.main(args=sys.argv[1:], prog_name="python -m flask" if as_module else None)
  File "/app/.heroku/python/lib/python3.6/site-packages/flask/cli.py", line 586, in main
    return super(FlaskGroup, self).main(*args, **kwargs)
  File "/app/.heroku/python/lib/python3.6/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/app/.heroku/python/lib/python3.6/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/app/.heroku/python/lib/python3.6/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/app/.heroku/python/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/app/.heroku/python/lib/python3.6/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/app/.heroku/python/lib/python3.6/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/app/.heroku/python/lib/python3.6/site-packages/flask/cli.py", line 426, in decorator
    return __ctx.invoke(f, *args, **kwargs)
  File "/app/.heroku/python/lib/python3.6/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/app/.heroku/python/lib/python3.6/site-packages/flask_migrate/cli.py", line 134, in upgrade
    _upgrade(directory, revision, sql, tag, x_arg)
  File "/app/.heroku/python/lib/python3.6/site-packages/flask_migrate/__init__.py", line 96, in wrapped
    f(*args, **kwargs)
  File "/app/.heroku/python/lib/python3.6/site-packages/flask_migrate/__init__.py", line 271, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/app/.heroku/python/lib/python3.6/site-packages/alembic/command.py", line 298, in upgrade
    script.run_env()
  File "/app/.heroku/python/lib/python3.6/site-packages/alembic/script/base.py", line 489, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/app/.heroku/python/lib/python3.6/site-packages/alembic/util/pyfiles.py", line 98, in load_python_file
    module = load_module_py(module_id, path)
  File "/app/.heroku/python/lib/python3.6/site-packages/alembic/util/compat.py", line 184, in load_module_py
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "migrations/env.py", line 27, in <module>
    str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%'))
AttributeError: 'NoneType' object has no attribute 'engine'

I think the upgrade is where the problem is hence the error AttributeError: 'NoneType' object has no attribute 'engine'

How can I solve this?

I have tried:

$ heroku pg:push mylocaldb HEROKU_POSTGRESQL_MAGENTA --app sushi

...replacing the placeholders with my own values but it still does not work. SO has other similar db-related issues such as this and this but none really answers my issue.

Upvotes: 0

Views: 636

Answers (1)

Gitau Harrison
Gitau Harrison

Reputation: 3517

I have found a way around it. Looking at my application factory, I missed to add db argument when initializing migrate. All I needed to do was to add db to it.

Initially:

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

    login.init_app(app)
    db.init_app(app)
    migrate.init_app(app) #<---------------
    moment.init_app(app)
    babel.init_app(app)
    mail.init_app(app)
    bootstrap.init_app(app)
    

Fixed error:

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

    login.init_app(app)
    db.init_app(app)
    migrate.init_app(app, db) #<---------------
    moment.init_app(app)
    babel.init_app(app)
    mail.init_app(app)
    bootstrap.init_app(app)
    

Now, when I run python heroku run flask db upgrade, the PostreSQL tables are updated and I can see them. Appreciation goes to this post.

Upvotes: 1

Related Questions