我一直在学习 Flask Web 应用程序框架并且对它感觉很舒服。我以前构建了一个简单易用的应用程序,它运行良好。我在同一个项目上工作,但尝试使用 TDD 来实现它。我遇到了以前从未见过的数据库错误,不知道如何修复。
当我检查我的代码时,我看不到任何问题。它看起来也与工作项目的代码相同,所以我真的不知道我做错了什么。
这里是错误:
(env) PS C:\coding-projects\task-master-tdd> flask shell
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)] on win32
App: project [development]
Instance: C:\coding-projects\task-master-tdd\instance
>>> from project import db
>>> db
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 1060, in __repr__
self.engine.url if self.app or current_app else None
File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 943, in engine
return self.get_engine()
File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 962, in get_engine
return connector.get_engine()
File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 555, in get_engine
options = self.get_options(sa_url, echo)
File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 570, in get_options
self._sa.apply_driver_hacks(self._app, sa_url, options)
File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 914, in apply_driver_hacks
sa_url.database = os.path.join(app.root_path, sa_url.database)
AttributeError: can't set attribute
>>>
我的 config.py 文件:
import os
# load the environment variables from the .env file
from dotenv import load_dotenv
load_dotenv()
# Determine the folder of the top-level directory of this project
BASEDIR = os.path.abspath(os.path.dirname(__file__))
class Config:
FLASK_ENV = 'development'
TESTING = False
DEBUG = False
SECRET_KEY = os.getenv('SECRET_KEY', default='A very terrible secret key.')
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL',
default=f"sqlite:///{os.path.join(BASEDIR, 'instance', 'app.db')}")
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL',
default=f"sqlite:///{os.path.join(BASEDIR, 'instance', 'test.db')}")
class ProductionConfig(Config):
FLASK_ENV = 'production'
我的用户模型:
from project import db, login_manager
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True)
hashed_password = db.Column(db.String)
def __init__(self, username, password):
self.username = username
self.hashed_password = generate_password_hash(password)
def is_password_valid(self, password):
return check_password_hash(self.hashed_password, password)
def __repr__(self):
return '<User {}>'.format(self.id)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
答案 0 :(得分:36)
如果您遇到这种情况,将 Flask-SQLAlchemy 升级到 >= 2.5 应该可以解决每个 https://github.com/pallets/flask-sqlalchemy/issues/910#issuecomment-802098285 的问题。
不再需要将 SQLAlchemy 固定到 ~1.3。
我早些时候遇到过这个问题,但我想我已经弄清楚发生了什么。
SQLAlchemy 自动安装为 Flask-SQLAlchemy 的依赖项,其最新版本 (1.4.0) 引入了以下重大更改:
<块引用>URL 对象现在是一个不可变的命名元组。要修改 URL 对象,请使用 URL.set() 方法生成新的 URL 对象。
我只需安装先前版本的 SQL Alchemy (1.3.23) 即可解决此问题。
答案 1 :(得分:9)
通过运行双重检查此问题是否对您有影响
pip freeze
您应该会发现 sqlalchemy 的当前版本是 1.4.0。我发现目前最快的解决方案是手动恢复到以前版本的 sqlalchemy:
pip install SQLAlchemy==1.3.23
如果您刚刚恢复到以前的版本并且它可以工作,那么现在是固定您的版本的好时机:
pip freeze > requirements.txt
答案 2 :(得分:1)
我能够通过将我的 sql-alchemy
版本固定到低于 1.4.0
来解决这个问题。上面列出了类似的例子。以下是我为解决此问题所做的步骤,直到出现补丁。
冻结您的包裹
pip freeze > requirements.txt
更新您的 requirements.txt 中的 SQLAlchemy
SQLAlchemy<1.4.0
重新安装软件包
pip install -r requirements.txt
有关如何执行此操作的更多信息,请参阅 pip 文档:https://pip.pypa.io/en/stable/
答案 3 :(得分:1)
确认npburns224's / SuperShoot's answer:
将 Flask-SQLAlchemy
(以及它的依赖项 SQLAlchemy
)升级到最新版本对我很有帮助。
pip install --upgrade flask-sqlalchemy
我现在正在成功运行 Flask-SQLAlchemy 2.5.1
和 SQLAlchemy 1.4.3
。
答案 4 :(得分:0)
刚刚面临完全相同的错误。事实证明,我安装了错误的 Flask-SQLAlchemy 库。我使用 conda 而不是 pip 安装了它,conda 为我的操作系统和环境安装了合适的。
conda install Flask-SQLAlchemy
答案 5 :(得分:0)
Flask-SQLAlchemy==2.5.1 解决我同样的问题
答案 6 :(得分:-3)
我通过覆盖 SQLAlchemy 类中的 apply_driver_hacks 解决了这个问题。
在这个新方法中,我删除了这一行:sa_url.database = os.path.join(app.root_path, sa_url.database)
。我复制了其余的方法。
class MySQLAlchemy(SQLAlchemy):
def apply_driver_hacks(self, app, sa_url, options):
...
该方法可以找到here。我描述的修复应该只是暂时的。该问题可能会在较新版本的 flask-sqlalchemy 中得到解决。