Apply Custom Sorting to Table Columns within CREATE TABLE
This example illustrates use of the Rewriter object introduced at Fine-Grained Autogenerate Generation with Rewriters. While the rewriter grants access to the individual ops.MigrateOperation objects, there are sometimes some special techniques required to get around some structural limitations that are present.
此示例说明了 使用重写器在细粒度自动生成 中介绍的 Rewriter 对象的使用。 虽然重写器授予对单个 ops.MigrateOperation 对象的访问权限,但有时需要一些特殊技术来解决存在的一些结构限制。
One is when trying to reorganize the order of columns in a table within a ops.CreateTableOp directive. This directive, when generated by autogenerate, actually holds onto the original Table
object as the source of its information, so attempting to reorder the ops.CreateTableOp.columns
collection will usually have no effect. Instead, a new ops.CreateTableOp object may be constructed with the new ordering. However, a second issue is that the Column
objects inside will already be associated with the Table
that is from the model being autogenerated, meaning they can’t be reassigned directly to a new Table
. To get around this, we can copy all the columns and constraints using methods like Column.copy().
一种是尝试在 ops.CreateTableOp 指令中重新组织表中列的顺序时。 该指令在由 autogenerate 生成时,实际上保留原始
Table
对象作为其信息的来源,因此尝试重新排序ops.CreateTableOp.columns
集合通常不会有任何效果。 相反,可以使用新的排序构造一个新的 ops.CreateTableOp 对象。 然而,第二个问题是内部的Column
对象已经与来自正在自动生成的模型的表相关联,这意味着它们不能直接重新分配给新表。 为了解决这个问题,我们可以使用 Column.copy() 等方法复制所有列和约束。
Below we use Rewriter to create a new ops.CreateTableOp directive and to copy the Column
objects from one into another, copying each column or constraint object and applying a new sorting scheme:
下面我们使用 Rewriter 创建一个新的 ops.CreateTableOp 指令并将
Column
对象从一个复制到另一个,复制每个列或约束对象并应用新的排序方案:
# in env.py
from alembic.operations import ops
from alembic.autogenerate import rewriter
writer = rewriter.Rewriter()
@writer.rewrites(ops.CreateTableOp)
def order_columns(context, revision, op):
special_names = {"id": -100, "created_at": 1001, "updated_at": 1002}
cols_by_key = [
(
special_names.get(col.key, index)
if isinstance(col, Column)
else 2000,
col.copy(),
)
for index, col in enumerate(op.columns)
]
columns = [
col for idx, col in sorted(cols_by_key, key=lambda entry: entry[0])
]
return ops.CreateTableOp(
op.table_name, columns, schema=op.schema, **op.kw)
# ...
context.configure(
# ...
process_revision_directives=writer
)
Above, when we apply the writer
to a table such as:
上面,当我们将 writer 应用于表时,例如:
Table(
"my_table",
m,
Column("data", String(50)),
Column("created_at", DateTime),
Column("id", Integer, primary_key=True),
Column("updated_at", DateTime),
UniqueConstraint("data", name="uq_data")
)
This will render in the autogenerated file as:
这将在自动生成的文件中呈现为:
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"my_table",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("data", sa.String(length=50), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("updated_at", sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("data", name="uq_data"),
)
# ### end Alembic commands ###