作者:我非英雄丶广目无双丶_398 | 来源:互联网 | 2023-01-26 14:43
我跟着一本书尝试创建Flask博客。我是Flask的新手。我更新了一个模型,因此代码如下所示:
class Entry(db.Model):
STATUS_PUBLIC = 0
STATUS_DRAFT = 1
STATUS_DELETED = 2
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100))
slug = db.Column(db.String(100), unique=True)
body = db.Column(db.Text)
status = db.Column(db.SmallInteger, default=STATUS_PUBLIC)
created_timestamp = db.Column(db.DateTime, default=datetime.datetime.now)
modified_timestamp = db.Column(
db.DateTime,
default=datetime.datetime.now,
Onupdate=datetime.datetime.now)
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
添加最后一行author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
会导致数据库升级失败,并显示以下错误:
File "manage.py", line 5, in
manager.run()
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/flask_script/__init__.py", line 412, in run
result = self.handle(sys.argv[0], sys.argv[1:])
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/flask_script/__init__.py", line 383, in handle
res = handle(*args, **config)
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/flask_script/commands.py", line 216, in __call__
return self.run(*args, **kwargs)
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/flask_migrate/__init__.py", line 259, in upgrade
command.upgrade(config, revision, sql=sql, tag=tag)
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/command.py", line 254, in upgrade
script.run_env()
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/script/base.py", line 425, in run_env
util.load_python_file(self.dir, 'env.py')
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/util/pyfiles.py", line 93, in load_python_file
module = load_module_py(module_id, path)
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/util/compat.py", line 75, in load_module_py
mod = imp.load_source(module_id, path, fp)
File "migrations/env.py", line 87, in
run_migrations_online()
File "migrations/env.py", line 80, in run_migrations_online
context.run_migrations()
File "", line 8, in run_migrations
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/runtime/environment.py", line 836, in run_migrations
self.get_context().run_migrations(**kw)
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/runtime/migration.py", line 330, in run_migrations
step.migration_fn(**kw)
File "/home/devblog/projects/blog/app/migrations/versions/6b49bdaf06ce_.py", line 22, in upgrade
batch_op.create_foreign_key(None, 'user', ['author_id'], ['id'])
File "/usr/lib64/python2.7/contextlib.py", line 24, in __exit__
self.gen.next()
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/operations/base.py", line 299, in batch_alter_table
impl.flush()
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/operations/batch.py", line 80, in flush
fn(*arg, **kw)
File "/home/devblog/projects/blog/venv/lib/python2.7/site-packages/alembic/operations/batch.py", line 337, in add_constraint
raise ValueError("Constraint must have a name")
ValueError: Constraint must have a name
问题似乎与迁移脚本的升级功能有关:
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('entry', schema=None) as batch_op:
#batch_op.create_foreign_key(None, 'user', ['author_id'], ['id'])
batch_op.create_foreign_key("author_id", 'user', ['author_id'], ['id'])
我通过注释掉原始行,删除None
并使用来“修复”此问题'author_id'
。
我使用了http://alembic.zzzcomputing.com/en/latest/ops.html上的文档来提出修复程序。相关部分:
create_foreign_key(约束名称,source_table,referent_table,local_cols,remote_cols,Onupdate= None,Ondelete= None,deferrable = None,初始= None,match = None,source_schema = None,referent_schema = None,** dialect_kw)
这将在内部生成一个包含必要列的Table对象,然后生成一个新的ForeignKeyConstraint对象,然后将其与Table关联。与该操作关联的任何事件侦听器都将正常触发。AddConstraint构造最终用于生成ALTER语句。
参数:name-外键约束的名称。该名称是必需的,以便可以发出ALTER语句。对于使用自动命名方案的设置(例如在配置约束命名约定中描述的设置),此处的名称可以为None,因为事件侦听器在将约束名称与表关联时会将其应用于约束对象。source_table –源表的字符串名称。referent_table –目标表的字符串名称。local_cols –源表中字符串列名称的列表。remote_cols –远程表中的字符串列名称的列表。onupdate –可选字符串。如果设置,则在为此约束发布DDL时发出ON UPDATE。典型值包括CASCADE,DELETE和RESTRICT。ondelete –可选字符串。如果设置,则在为此约束发布DDL时发出ON DELETE。典型值包括CASCADE,DELETE和RESTRICT。可延期–可选布尔。如果设置,则在为此约束发出DDL时发出DEFERRABLE或NOT DEFERRABLE。source_schema –源表的可选架构名称。referent_schema¶–目标表的可选架构名称。
我认为我添加了一个约束名称而不是None
,从而“解决了”问题。它是否正确?
同样,该函数似乎需要5个自变量。仅用4个怎么工作?
任何建议表示感谢。
1> shad0w_wa1k3..:
对于添加一个简单的外键列的情况,Mark Steward的解决方案对我来说非常理想。
无论您在哪里声明/定义“ db”,请执行以下操作-
from sqlalchemy import MetaData
naming_cOnvention= {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
db = SQLAlchemy(metadata=MetaData(naming_cOnvention=naming_convention))
然后,在您初始化迁移应用程序(烧瓶迁移)的地方,传递render_as_batch=True
-
migrate.init_app(app, db, render_as_batch=True)