P4n*_*1n0 6 python sqlalchemy flask python-3.x flask-sqlalchemy
使用 Flask 的应用程序工厂模式时,我无法将表创建到数据库 (PostgresSQL) 中。
我查看了Stackoverflow和 Flask-SQLAlchemy 源代码中的不同示例。我的理解是,使用工厂应用程序模式,我需要先设置所谓的上下文,然后才能尝试创建表。但是,当我创建上下文时,Flask 应用程序的配置字典会重置,并且不会向前传播配置。
这是我的model.py
import datetime
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class MyModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
some = db.Column(db.DateTime, nullable=False)
random = db.Column(db.String, nullable=False)
model = db.Column(db.String, nullable=False)
fields = db.Column(db.Integer, nullable=False)
def __init__(self, some: datetime.datetime, random: str, model: str,
fields: int) -> None:
self.some = some
self.random = random
self.model = model
self.fields = fields
def __repr__(self):
return f"""<MyModel(some={self.some}, random={self.random},
model={self.model}, fields={self.fields})>"""
Run Code Online (Sandbox Code Playgroud)
这是应用程序的__init__.py
文件
import os
from flask import Flask
from flask_migrate import Migrate
from myapp.models import db
migrate = Migrate()
def create_app(config):
app = Flask(__name__)
app.config.from_object(config)
db.init_app(app)
migrate.init_app(app, db)
from .models import MyModel
with app.app_context():
db.create_all()
@app.route('/hello')
def hello():
return('Hello World!')
return app
Run Code Online (Sandbox Code Playgroud)
我还有一个main.py
文件:
from myapp import create_app
from config import Config
app = create_app(Config)
if __name__ == "__main__":
app.run(host='127.0.0.1', port=8080, debug=True)
Run Code Online (Sandbox Code Playgroud)
根文件夹包含main.py
和MyModule
app 文件夹。此外,我在文件中设置了一个 Postgres 实例和所需的配置常量config.py
:
import os
from dotenv import load_dotenv
basedir = os.path.abspath(__file__)
load_dotenv(os.path.join(basedir, '.env'))
class Config(object):
DEBUG = False
TESTING = False
CSRF_ENABLED = True
SECRET_KEY = os.environ.get('SECRET_KEY')
SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI')
SQLALCHEMY_TRACK_MODIFICATIONS = False
Run Code Online (Sandbox Code Playgroud)
我正在从 .env 文件读取变量。
当我运行时main.py
,出现以下错误:
(venv) $:project-name username$ python main.py
Traceback (most recent call last):
File "main.py", line 4, in <module>
app = create_app(Config)
File "/Users/username/project-name/myapp/__init__.py", line 18, in create_app
db.create_all()
File "/Users/username/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 1033, in create_all
self._execute_for_all_tables(app, bind, 'create_all')
File "/Users/username/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 1025, in _execute_for_all_tables
op(bind=self.get_engine(app, bind), **extra)
File "/Users/username/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 956, in get_engine
return connector.get_engine()
File "/Users/username/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 560, in get_engine
options = self.get_options(sa_url, echo)
File "/Users/username/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 575, in get_options
self._sa.apply_driver_hacks(self._app, sa_url, options)
File "/Users/username/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 877, in apply_driver_hacks
if sa_url.drivername.startswith('mysql'):
AttributeError: 'NoneType' object has no attribute 'drivername'
Run Code Online (Sandbox Code Playgroud)
现在奇怪的是,当我print(app.config)
在 create_app 函数中打印时,配置就位,就像我想要的那样。例如SQLALCHEMY_DATABASE_URI=postgresql://testuser:testpassword@localhost:5432/testdb'
。但是,当我在 app.app_context() 循环内打印相同的信息时SQLALCHEMY_DATABASE_URI=None
(例如,其他键值对也被重置)。
我在这里缺少什么?
您加载.env
文件的方式不正确:
basedir = os.path.abspath(__file__)
load_dotenv(os.path.join(basedir, '.env'))
Run Code Online (Sandbox Code Playgroud)
basedir
是模块文件本身,而不是目录。因此,对于名为 的文件config.py
,basedir
设置为/..absolutepath../config.py
,而不是/..absolutepath../config.py
。结果,您要求dotenv()
加载该文件/..absolutepath../config.py/.env
,该文件不存在。
您未接os.path.dirname()
来电:
basedir = os.dirname(os.path.abspath(__file__))
Run Code Online (Sandbox Code Playgroud)
您可以使用以下方法完全避免此问题dotenv.find_dotenv()
:
load_dotenv(find_dotenv())
Run Code Online (Sandbox Code Playgroud)
它使用__file__
调用它的模块的属性。
其他备注:
db.create_all()
. 而是使用Flask CLI和 Flask Migrate 命令(flask db init
、flask db migrate
、 和flask db upgrade
创建迁移目录和初始迁移脚本,然后升级连接的数据库以使用最新的架构版本。config
如果您只是从当前项目导入适用于所有开发的默认配置,那么使用 Flask 应用程序工厂会更容易。您始终可以根据需要使用可选参数和环境变量通过app.config.from_obj()
或app.config.from_envvar()
加载更多配置。 归档时间: |
|
查看次数: |
4260 次 |
最近记录: |