为什么 Flask Migrations 没有检测到字段的长度变化?
Why Flask Migrations does not detect a field's length change?
我有以下模型,我想更改名称的长度,当我进行迁移时它没有检测到更改
class Client(db.Model):
__tablename__ = "client"
client_id = db.Column(
db.Integer,
primary_key=True,
autoincrement=True
)
name = db.Column(db.String(65))
email = db.Column(db.String(255))
例如改为
name = db.Column(db.String(100))
NFO [alembic.env] No changes in schema detected.
但是当我更改名称时,如果它检测到更改
INFO [alembic.autogenerate.compare] Detected added column 'client.name_test'
INFO [alembic.autogenerate.compare] Detected removed column 'client.name'
更新 - 2020 年 6 月
Alembic 1.4 中的类型比较已更改,因此应更可靠地识别字段长度更改。来自更新日志:
A major rework of the “type comparison” logic is in place which
changes the entire approach by which column datatypes are compared.
Types are now compared based on the DDL string generated by the
metadata type vs. the datatype reflected from the database. This means
we compare types based on what would actually render and additionally
if elements of the types change like string length, those changes are
detected as well. False positives like those generated between
SQLAlchemy Boolean and MySQL TINYINT should also be resolved. Thanks
very much to Paul Becotte for lots of hard work and patience on this
one.
更改日志还引用了this issue and this documentation。
原答案
TL;DR:
context.configure(
# ...
compare_type = True
)
我已经在 PG 后端的字符串长度变化上对此进行了测试,它确实有效,但是正如您在下面看到的,文档目前声明它不应该。这是 relevant section of the docs:
Autogenerate can optionally detect:
- Change of column type. This will occur if you set the
EnvironmentContext.configure.compare_type parameter to True, or to a
custom callable function. The default implementation only detects
major type changes, such as between Numeric and String, and does not
detect changes in arguments such as lengths, precisions, or
enumeration members. The type comparison logic is extensible to work
around these limitations, see Comparing Types for details.
API compare_type
的参考指出:
Indicates type comparison behavior during an autogenerate operation.
Defaults to False which disables type comparison. Set to True to turn
on default type comparison, which has varied accuracy depending on
backend. See Comparing Types for an example as well as information on
other type comparison options.
最后,在标题为 Comparing Types 的部分中,以下示例给出了如何启用类型比较:
context.configure(
# ...
compare_type = True
)
您会在 env.py
脚本中找到 context.configure()
调用,该脚本由嵌套在连接上下文中的 alembic 自动生成:
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
... 并在其中添加 compare_type
参数。
在同一节中,他们继续说:
Note The default type comparison logic (which is end-user extensible)
currently works for major changes in type only, such as between
Numeric and String. The logic will not detect changes such as:
changes between types that have the same “type affinity”, such as
between VARCHAR and TEXT, or FLOAT and NUMERIC
changes between the arguments within the type, such as the lengths of
strings, precision values for numerics, the elements inside of an
enumeration.
Detection of these kinds of parameters is a long term project on the SQLAlchemy side.
所以有趣的是看到它在文档中多次提到这不应该起作用。如前所述,我已经在 postgres 上对此进行了测试,并且可以确认设置 compare_type=True
确实会生成列长度的修订版,因此文档可能在这方面有点落后,或者维护者还没有准备好尚未将其声明为一项功能。
我还在 MySQL 上进行了测试,可以确认如果 compare_type=True
.
也可以检测到字符串长度的变化
我有以下模型,我想更改名称的长度,当我进行迁移时它没有检测到更改
class Client(db.Model):
__tablename__ = "client"
client_id = db.Column(
db.Integer,
primary_key=True,
autoincrement=True
)
name = db.Column(db.String(65))
email = db.Column(db.String(255))
例如改为
name = db.Column(db.String(100))
NFO [alembic.env] No changes in schema detected.
但是当我更改名称时,如果它检测到更改
INFO [alembic.autogenerate.compare] Detected added column 'client.name_test'
INFO [alembic.autogenerate.compare] Detected removed column 'client.name'
更新 - 2020 年 6 月
Alembic 1.4 中的类型比较已更改,因此应更可靠地识别字段长度更改。来自更新日志:
A major rework of the “type comparison” logic is in place which changes the entire approach by which column datatypes are compared. Types are now compared based on the DDL string generated by the metadata type vs. the datatype reflected from the database. This means we compare types based on what would actually render and additionally if elements of the types change like string length, those changes are detected as well. False positives like those generated between SQLAlchemy Boolean and MySQL TINYINT should also be resolved. Thanks very much to Paul Becotte for lots of hard work and patience on this one.
更改日志还引用了this issue and this documentation。
原答案
TL;DR:
context.configure(
# ...
compare_type = True
)
我已经在 PG 后端的字符串长度变化上对此进行了测试,它确实有效,但是正如您在下面看到的,文档目前声明它不应该。这是 relevant section of the docs:
Autogenerate can optionally detect:
- Change of column type. This will occur if you set the EnvironmentContext.configure.compare_type parameter to True, or to a custom callable function. The default implementation only detects major type changes, such as between Numeric and String, and does not detect changes in arguments such as lengths, precisions, or enumeration members. The type comparison logic is extensible to work around these limitations, see Comparing Types for details.
API compare_type
的参考指出:
Indicates type comparison behavior during an autogenerate operation. Defaults to False which disables type comparison. Set to True to turn on default type comparison, which has varied accuracy depending on backend. See Comparing Types for an example as well as information on other type comparison options.
最后,在标题为 Comparing Types 的部分中,以下示例给出了如何启用类型比较:
context.configure(
# ...
compare_type = True
)
您会在 env.py
脚本中找到 context.configure()
调用,该脚本由嵌套在连接上下文中的 alembic 自动生成:
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
... 并在其中添加 compare_type
参数。
在同一节中,他们继续说:
Note The default type comparison logic (which is end-user extensible) currently works for major changes in type only, such as between Numeric and String. The logic will not detect changes such as:
changes between types that have the same “type affinity”, such as between VARCHAR and TEXT, or FLOAT and NUMERIC
changes between the arguments within the type, such as the lengths of strings, precision values for numerics, the elements inside of an enumeration.
Detection of these kinds of parameters is a long term project on the SQLAlchemy side.
所以有趣的是看到它在文档中多次提到这不应该起作用。如前所述,我已经在 postgres 上对此进行了测试,并且可以确认设置 compare_type=True
确实会生成列长度的修订版,因此文档可能在这方面有点落后,或者维护者还没有准备好尚未将其声明为一项功能。
我还在 MySQL 上进行了测试,可以确认如果 compare_type=True
.