1

I am getting "AttributeError: 'NoneType' object has no attribute 'drivername'" when trying to connect to an existing empty PostgreSQL db on localhost from Flask app.

Here's .env:

...
SQLALCHEMY_DATABASE_URI='postgresql+psycopg2://postgres:PASSWORD@localhost/DATABASE' 
...

Here's config:

import os

basedir = os.path.abspath(os.path.dirname(__file__))

class Config(object):
    DEBUG = False
    TESTING = False
    SECRET_KEY = os.environ.get('SECRET_KEY')
    SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class ProdConfig(Config):
    DEBUG = False

class StagingConfig(Config):
    DEVELOPMENT = True
    DEBUG = True

class DevConfig(Config):
    DEVELOPMENT = True
    DEBUG = True

class TestConfig(Config):
    TESTING = True

Here's app.extensions:

from flask_sqlalchemy import SQLAlchemy

db=SQLAlchemy()
...

And here's __init__:

from flask import Flask, Blueprint...
from . config import Config
from flask_login import LoginManager
from flask_migrate import Migrate
from pathlib import Path

login_manager = LoginManager()
login_manager.login_view = 'auth.login'

def create_app():
    app = Flask(__name__,
                static_url_path='',
                static_folder='../app/static',
                template_folder='../app/templates')

    app.config.from_object(Config)

    from .extensions import db
    db.init_app(app)

    Migrate(app, db)
    
    from .templates.auth import auth_bp
    from .views.main import main_bp

    app.register_blueprint(main_bp)
    app.register_blueprint(auth_bp, url_prefix='/auth')

    login_manager.init_app(app)

    return app

I've checked the following Stackoverflow answers:

db.create_all() 'NoneType' object has no attribute 'drivername',

SQLAlchemy: 'NoneType' object has no attribute 'drivername',

SQLAlchemy cannot connect to Postgresql on localhost,

Flask app gives a " 'NoneType' object has no attribute 'drivername' " error

and all of them seem to point to errors in SQLALCHEMY_DATABASE_URI declaration.

This doesn't solve my problem. I have tried

>>> from app.extensions import db
>>> db.create_all()

and

>>> from app import create_app 
>>> app = create_app()
>>> from app.extensions import db
>>> db.create_all()

and

>>> from app import create_app
>>> app=create_app()
>>> app.app_context().push() 
>>> from app.extensions import db
>>> db.create_all()

The results are the same.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\...\venv\lib\site-packages\flask_sqlalchemy\__init__.py", line 1039, in create_all
    self._execute_for_all_tables(app, bind, 'create_all')
  File "C:\Users\...\venv\lib\site-packages\flask_sqlalchemy\__init__.py", line 1031, in _execute_for_all_tables        
    op(bind=self.get_engine(app, bind), **extra)
  File "C:\Users\...\venv\lib\site-packages\flask_sqlalchemy\__init__.py", line 962, in get_engine
    return connector.get_engine()
  File "C:\Users\...\venv\lib\site-packages\flask_sqlalchemy\__init__.py", line 555, in get_engine
    options = self.get_options(sa_url, echo)
  File "C:\Users\...\venv\lib\site-packages\flask_sqlalchemy\__init__.py", line 570, in get_options
    self._sa.apply_driver_hacks(self._app, sa_url, options)
  File "C:\Users\...\venv\lib\site-packages\flask_sqlalchemy\__init__.py", line 883, in apply_driver_hacks
    if sa_url.drivername.startswith('mysql'):
AttributeError: 'NoneType' object has no attribute 'drivername'

Any help will be greatly appreciated.

grommit
  • 169
  • 2
  • 14
  • 1
    I would check that the environment variable `SQLALCHEMY_DATABASE_URI` is definitely being set, for example by printing/logging its value. – snakecharmerb Jan 29 '21 at 17:40
  • 1
    Is `python-dotenv` installed? Otherwise `Flask` doesn’t support `.env` files. – rfkortekaas Jan 29 '21 at 17:45
  • pyhton-dotenv is installed. Checking the env variable leads to a negative answer ``` >>> import os >>> print(os.environ['SQLALCHEMY_DATABASE_URI']) Traceback (most recent call last): File "", line 1, in File "C:\DevProgs\Python38\lib\os.py", line 675, in __getitem__ raise KeyError(key) from None KeyError: 'SQLALCHEMY_DATABASE_URI' ``` – grommit Jan 29 '21 at 17:51
  • 1
    Can you try `from dotenv import load_dotenv` then `load_dotenv()` and then `os.getenv('SQLALCHEMY_DATABASE_URI')`? – rfkortekaas Jan 29 '21 at 18:02
  • 1
    `>>> load_dotenv()` `Python-dotenv could not parse statement starting at line 2` `True` `>>>` – grommit Jan 29 '21 at 18:04
  • 1
    Can you add your complete `.env` file. The mistake is somewhere in that file! Please make sure to remove sensitive data but keep the structure and names! – rfkortekaas Jan 29 '21 at 18:09
  • Fixed line 2... `>>> os.getenv('SQLALCHEMY_DATABASE_URI') ` `Traceback (most recent call last):` `File "", line 1, in ` `NameError: name 'os' is not defined` – grommit Jan 29 '21 at 18:21
  • 1
    Fixed that! Thank you! Getting errors about foreign keys now, but that's a totally separate topic! – grommit Jan 29 '21 at 18:25

1 Answers1

2

Solved by @rfkortekaas:

>>> from dotenv import load_dotenv
>>> load_dotenv()
>>> import os
>>> os.getenv('SQLALCHEMY_DATABASE_URI')
>>> from app import create_app
>>> app = create_app()
>>> app.app_context().push()   
>>> from app.extensions import db
>>> db.create_all()
grommit
  • 169
  • 2
  • 14