Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am following the CS50's Web Programming with Python and Javascript and in Lecture4 I have had the following error trying to create a postgresql database table:

 Traceback (most recent call last):
  File "create.py", line 19, in <module>
    main()
  File "create.py", line 15, in main
    db.create_all()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask_sqlalchemy/__init__.py", line 963, in create_all
    self._execute_for_all_tables(app, bind, 'create_all')
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask_sqlalchemy/__init__.py", line 955, in _execute_for_all_tables
    op(bind=self.get_engine(app, bind), **extra)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask_sqlalchemy/__init__.py", line 896, in get_engine
    return connector.get_engine()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask_sqlalchemy/__init__.py", line 556, in get_engine
    self._sa.apply_driver_hacks(self._app, info, options)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flask_sqlalchemy/__init__.py", line 830, in apply_driver_hacks
    if info.drivername.startswith('mysql'):
AttributeError: 'NoneType' object has no attribute 'drivername'

The code that I have used is in two python file: The first 1 called models.py:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Flight(db.Model):
    __tablename__ = "flights"
    id = db.Column(db.Integer, primary_key=True)
    origin = db.Column(db.String, nullable=False)
    destination = db.Column(db.String, nullable=False)
    duration = db.Column(db.Integer, nullable=False)

class Passenger(db.Model):
    __tablename__ = "passengers"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    flight_id = db.Column(db.Integer, db.ForeignKey("flight.id"), nullable=False)

The second file is called create.py:

import os

from flask import Flask, render_template, request
from models import *

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("postgresql://postgres:password@localhost/database1")
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)

def main():
    db.create_all()

if __name__ == "__main__":
    with app.app_context():
        main()

Can you help me?!

like image 636
Dawlat Moustafa Avatar asked Apr 13 '19 15:04

Dawlat Moustafa


3 Answers

I think this is an issue with how you're attempting to connect to your Postgres database:

app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("postgresql://postgres:password@localhost/database1")

you probably want this line to be the following instead:

app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://postgres:password@localhost/database1"

since the os.getenv(...) is currently trying to get an environment variable on your system named: "postgresql://postgres:password@localhost/database1" and you surely didn't set up an environment variable with this name.. Which is why you're getting a NoneType error for your postgres driver:

AttributeError: 'NoneType' object has no attribute 'drivername'.

If you want to use an environment variable to get your database connection string, do something like the following in your .bash_profile or .bashrc file:

export SQLALCHEMY_DATABASE_URI='postgresql://postgres:password@localhost/database1'

then change your database connection code to the following:

app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get('SQLALCHEMY_DATABASE_URI')

Hopefully that makes sense!

like image 174
Nathan Avatar answered Oct 27 '22 23:10

Nathan


To clarify gbajson's answer, os.getenv gets a value from a specific environment variable. You either need to store the database URI in an env var (before you start Flask) and get it from there:

app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("DATABASE_URI")

or, hard code it directly as a string without using getenv:

app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://postgres:password@localhost/database1"
like image 43
Daniel Roseman Avatar answered Oct 27 '22 21:10

Daniel Roseman


Check line os.getenv("postgresql://postgres:password@localhost/database1")

It doesn't contain the name of the environment variable.

Reference: https://docs.python.org/3/library/os.html?highlight=getenv#os.getenv

Sample usage:

$ python
Python 3.7.0 (default, Aug 20 2018, 15:06:39) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os  
>>> editor = os.getenv('EDITOR')
>>> print(editor)
vi
like image 1
gbajson Avatar answered Oct 27 '22 23:10

gbajson