python - Flask App 未在 Heroku 中创建 Postgres 数据库/表(错误:AttributeError:'NoneType' 对象没有属性'drivername')
问题描述
我已经构建了一个在本地运行的基本烧瓶 API,但是现在我已经尝试将它部署到 Heroku,当我尝试运行它时,我得到了一个广泛的错误列表。经过一番调查,我发现应用程序没有从我部署的代码中创建自己的数据库。在本地,应用程序按计划工作,并在第一次运行时使用以下代码创建了数据库:
with app.app_context():
db.create_all()
在注意到我的部署中没有创建数据库之后,我尝试在 heroku 控制台中运行以下命令:
$ heroku run python
>>> from app import db
>>> db.create_all()
>>> exit()
但是,一旦我运行“从应用程序导入数据库”,我会收到以下错误消息:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/app/app.py", line 85, in <module>
db.create_all()
File "/app/.heroku/python/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 1039, in create_all
self._execute_for_all_tables(app, bind, 'create_all')
File "/app/.heroku/python/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 1031, in _execute_for_all_tables
op(bind=self.get_engine(app, bind), **extra)
File "/app/.heroku/python/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 962, in get_engine
return connector.get_engine()
File "/app/.heroku/python/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 555, in get_engine
options = self.get_options(sa_url, echo)
File "/app/.heroku/python/lib/python3.9/site-packages/flask_sqlalchemy/__init__.py", line 570, in get_options
self._sa.apply_driver_hacks(self._app, sa_url, options)
File "/app/.heroku/python/lib/python3.9/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'
我试图确定为什么命令行和我的代码此时都不会创建数据库。
我有以下 app.py 文件运行我的整个 api
from flask import Flask, request, jsonify
from flask_restful import Api, Resource, reqparse, fields, marshal_with
from flask_sqlalchemy import SQLAlchemy
from dotenv import load_dotenv
import os
import json
from dataclasses import dataclass
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
api = Api(app)
load_dotenv()
app.config['PROPAGATE_EXCEPTIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI']=os.environ.get('SQL_URI')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
db = SQLAlchemy(app)
@dataclass
class Player(db.Model):
id = db.Column(db.Integer, primary_key=True)
FIDE_Standard = db.Column(db.Integer, nullable=True)
FIDE_Rapid = db.Column(db.Integer, nullable=True)
FIDE_Blitz = db.Column(db.Integer, nullable=True)
USCF_Regular = db.Column(db.Integer, nullable=True)
USCF_Quick = db.Column(db.Integer, nullable=True)
USCF_Blitz = db.Column(db.Integer, nullable=True)
ChessCom_Bullet = db.Column(db.Integer, nullable=True)
ChessCom_Blitz = db.Column(db.Integer, nullable=True)
ChessCom_Rapid = db.Column(db.Integer, nullable=True)
ChessCom_Daily = db.Column(db.Integer, nullable=True)
ChessCom_Puzzle = db.Column(db.Integer, nullable=True)
LiChess_Bullet = db.Column(db.Integer, nullable=True)
LiChess_Blitz = db.Column(db.Integer, nullable=True)
LiChess_Rapid = db.Column(db.Integer, nullable=True)
LiChess_Classical = db.Column(db.Integer, nullable=True)
LiChess_Correspondence = db.Column(db.Integer, nullable=True)
LiChess_Puzzle = db.Column(db.Integer, nullable=True)
player_post_parser = reqparse.RequestParser()
player_post_parser.add_argument('FIDE', type=dict)
player_post_parser.add_argument('USCF', type=dict)
player_post_parser.add_argument('ChessCom', type = dict)
player_post_parser.add_argument('LiChess', type = dict)
# player_post_args= player_post_parser.parse_args()
FIDE_Parser = reqparse.RequestParser()
FIDE_Parser.add_argument('standard', type= int, location=('nested_one',))
FIDE_Parser.add_argument('rapid', type= int, location=('nested_one',))
FIDE_Parser.add_argument('blitz', type= int, location=('nested_one',))
# FIDE_args = FIDE_Parser.parse_args(req=player_post_args)
USCF_Parser = reqparse.RequestParser()
USCF_Parser.add_argument('regular', type=int, location=('nested_two',))
USCF_Parser.add_argument('quick', type=int, location=('nested_two',))
USCF_Parser.add_argument('blitz', type=int, location=('nested_two',))
# USCF_args = USCF_Parser.parse_args(req=player_post_args)
ChessCom_Parser = reqparse.RequestParser()
ChessCom_Parser.add_argument('bullet', type = int, location=('nexted_three',))
ChessCom_Parser.add_argument('blitz', type = int, location=('nexted_three',))
ChessCom_Parser.add_argument('rapid', type = int, location=('nexted_three',))
ChessCom_Parser.add_argument('daily', type = int, location=('nexted_three',))
ChessCom_Parser.add_argument('puzzle', type = int, location=('nexted_three',))
# ChessCom_args=ChessCom_Parser.parse_args(req=player_post_args)
LiChess_Parser = reqparse.RequestParser()
LiChess_Parser.add_argument('bullet', type = int, location=('nexted_four',))
LiChess_Parser.add_argument('blitz', type = int, location=('nexted_four',))
LiChess_Parser.add_argument('rapid', type = int, location=('nexted_four',))
LiChess_Parser.add_argument('classical', type = int, location=('nexted_four',))
LiChess_Parser.add_argument('correspondence', type = int, location=('nexted_four',))
LiChess_Parser.add_argument('puzzle', type = int, location=('nexted_four',))
with app.app_context():
db.create_all()
class Players(Resource):
def get(self):
result =Player.query.all()
player_list=[]
for player in result:
new_player={'FIDE':{
'standard':player.FIDE_Standard,
'rapid':player.FIDE_Rapid,
'blitz':player.FIDE_Blitz
},
'USCF':{
'regular':player.USCF_Regular,
'quick':player.USCF_Quick,
'blitz':player.USCF_Blitz
},
'ChessCom':{
'bullet':player.ChessCom_Bullet,
'blitz': player.ChessCom_Blitz,
'rapid':player.ChessCom_Rapid,
'daily':player.ChessCom_Daily,
'puzzle':player.ChessCom_Puzzle
},
'LiChess':{
'bullet':player.LiChess_Bullet,
'blitz':player.LiChess_Blitz,
'rapid':player.LiChess_Rapid,
'classical':player.LiChess_Classical,
'correspondence':player.LiChess_Correspondence,
'puzzle':player.LiChess_Puzzle
}
}
player_list.append(new_player)
return jsonify(player_list)
def post(self):
player_post_args = player_post_parser.parse_args()
FIDE_args=FIDE_Parser.parse_args(req=player_post_args)
USCF_args=USCF_Parser.parse_args(req=player_post_args)
ChessCom_args=ChessCom_Parser.parse_args(req=player_post_args)
LiChess_args=LiChess_Parser.parse_args(req=player_post_args)
player= Player(
FIDE_Standard= player_post_args['FIDE']['standard'],
FIDE_Rapid=player_post_args['FIDE']['rapid'],
FIDE_Blitz=player_post_args['FIDE']['blitz'],
USCF_Regular=player_post_args['USCF']['regular'],
USCF_Quick=player_post_args['USCF']['quick'],
USCF_Blitz=player_post_args['USCF']['blitz'],
ChessCom_Bullet=player_post_args['ChessCom']['bullet'],
ChessCom_Blitz=player_post_args['ChessCom']['blitz'],
ChessCom_Rapid=player_post_args['ChessCom']['rapid'],
ChessCom_Daily=player_post_args['ChessCom']['daily'],
ChessCom_Puzzle=player_post_args['ChessCom']['puzzle'],
LiChess_Bullet=player_post_args['LiChess']['bullet'],
LiChess_Blitz=player_post_args['LiChess']['blitz'],
LiChess_Rapid=player_post_args['LiChess']['rapid'],
LiChess_Classical=player_post_args['LiChess']['classical'],
LiChess_Correspondence=player_post_args['LiChess']['correspondence'],
LiChess_Puzzle=player_post_args['LiChess']['puzzle'],
)
db.session.add(player)
db.session.commit()
# return player
api.add_resource(Players, '/players')
if __name__ =="__main__":
app.run(debug=True)
解决方案
事实证明,在我的 heroku 设置和 app.py 文件中,我的 SQL DB url 的 .env 值有一个不同的名称。
推荐阅读
- javascript - 谷歌工作表脚本手动运行,但设置触发器不起作用
- ruby - 在 macos-catalina 上安装 cocoapods
- javascript - 我正在尝试制作一个颜色游戏来做出反应,但总是以不同的颜色结束
- python - 提取下三角形并将其投影到另一个二维空间
- android - 如何在 Dart 中使用 SecurityContext 的 setTrustedCertificates 函数?
- python - AttributeError:“WebElement”对象没有“滑动”属性
- c# - Blazor, run non static function when static string change
- macos - macOS 更新后 SSH “kex_exchange_identification”错误
- grafana - 如何解决 Grafana 面板插件中的 jsdoc PluginConflictError?
- ios - react-native run-ios 无法连接到开发服务器 npm:'7.19.1' 和节点:16.6.0,macincloud.com 环境