python - 将 sqlalchemy-continuum 与 flask-sqlalchemy 和 flask-migrate 一起使用
问题描述
我正在尝试让 sqlalchemy-continuum 与 flask-sqlalchemy 和 flask-migrate 一起工作。我的__init__.py
文件如下所示:
import os
from flask import Flask
def create_app():
"""Create and configure an instance of the Flask application."""
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SQLALCHEMY_DATABASE_URI='postgres+psycopg2://{}:{}@{}:{}/{}'.format(
os.environ['POSTGRES_USER'],
os.environ['POSTGRES_PASSWORD'],
os.environ['POSTGRES_HOST'],
os.environ['POSTGRES_PORT'],
os.environ['POSTGRES_DB']
),
SQLALCHEMY_TRACK_MODIFICATIONS=False
)
try:
os.makedirs(app.instance_path)
except OSError:
pass
from .models import db, migrate
db.init_app(app)
migrate.init_app(app, db)
return app
我的 models.py 文件如下所示:
import sqlalchemy
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from sqlalchemy_continuum import make_versioned
db = SQLAlchemy()
migrate = Migrate()
make_versioned(user_cls=None)
class User(db.Model):
__versioned__ = {}
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(20), unique=True, nullable=False)
def __repr__(self):
return '<User {} - {}>'.format(self.username, self.email)
sqlalchemy.orm.configure_mappers()
然后我运行以下 flask-migrate 命令来初始化和迁移数据库:
flask db init
flask db migrate
flask db upgrade
flask db upgrade 命令的输出似乎显示了正在创建的正确表:
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'transaction'
INFO [alembic.autogenerate.compare] Detected added table 'user'
INFO [alembic.autogenerate.compare] Detected added table 'user_version'
INFO [alembic.autogenerate.compare] Detected added index 'ix_user_version_end_transaction_id' on '['end_transaction_id']'
INFO [alembic.autogenerate.compare] Detected added index 'ix_user_version_operation_type' on '['operation_type']'
INFO [alembic.autogenerate.compare] Detected added index 'ix_user_version_transaction_id' on '['transaction_id']'
在 python shell 中,我可以执行以下操作:
>>> from test_flask.__init__ import create_app
>>> from test_flask.models import db, User
>>> app = create_app()
>>> with app.app_context():
... user = User(username='devuser', email='devuser@gmail.com',
password='devpassword')
... db.session.add(user)
... db.session.commit()
这似乎工作正常,但是当我尝试使用以下方式访问版本属性中的元素时:
>>> user.versions[0]
我收到以下错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/dynamic.py", line 254, in __getitem__
attributes.PASSIVE_NO_INITIALIZE).indexed(index)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/dynamic.py", line 359, in indexed
return list(self.added_items)[index]
IndexError: list index out of range
命令:
>>> user.versions
返回:
<sqlalchemy.orm.dynamic.AppenderQuery object at 0x7f6515d3a898>
这似乎不是sqlalchemy-continuum 文档中指定的版本属性的预期行为。关于我做错了什么有什么想法吗?
解决方案
此错误可能在两种情况下发生,至少:
UPDATE
你在一些或之后没有提交INSERT
- 或者你不在
app
上下文中
在您的烧瓶外壳示例中,所有语句都应位于上下文块内:
>>> with app.app_context():
... user = User(username='devuser2', email='devuser2@gmail.com', password='devpassword2')
... db.session.add(user)
... db.session.commit()
... user.versions[0].username
... user.username='devuser_fixed'
... db.session.commit()
... user.versions[1].username
#'devuser'
#'devuser_fixed'
在上下文之外,user
仍然是活的,变量留在内存中,但是连接到数据库的会话丢失了。
注意:如果缺少第二次提交,user.versions[1]
则仅在实际上下文会话中可用。因此,如果您退出此上下文并检查user.versions[1]
,您将面临同样的错误。
推荐阅读
- powershell - 在Powershell中提取数组的最后一行
- php - 如何从英国开放数据地理门户边界数据属性st_area(形状)中检索选区区域
- r - R - 传单地图未在 RStudio 或 Rshiny App 中加载 - 代理身份验证问题
- extwebcomponents - 如何使用 Alpha Vantage 股票数据呈现 ExtWebComponent 面积图?
- python - 如何将浮点数列表的 2d np.array 转换为浮点数的 2d np.array,将列表值堆叠到行
- animation - 使用快速滚动,使用 scrollmagic 拍摄的 tentmax 动画无法正常工作
- firebase - 使用 BLoC 进行 Flutter Firebase 电话身份验证
- swiftui - 如何在没有 navigationView 或 popover 的情况下切换视图?
- python - Python:将列表添加到字典中
- javascript - 如何选择在 Typescript 接口中嵌入一个或多个接口?