INFO [sqlalchemy.engine.base.Engine] {}
INFO [sqlalchemy.engine.base.Engine] COMMIT
+.. _cookbook_no_empty_migrations:
+
Don't Generate Empty Migrations with Autogenerate
=================================================
with context.begin_transaction():
context.run_migrations()
+.. _cookbook_dont_emit_drop_index:
+
Don't emit DROP INDEX when the table is to be dropped as well
=============================================================
include_object = include_object
)
+.. _cookbook_custom_sorting_create_table:
+
+Apply Custom Sorting to Table Columns within CREATE TABLE
+==========================================================
+
+This example illustrates use of the :class:`.Rewriter` object introduced
+at :ref:`autogen_rewriter`. While the rewriter grants access to the
+individual :class:`.ops.MigrateOperation` objects, there are sometimes some
+special techniques required to get around some structural limitations that
+are present.
+
+One is when trying to reorganize the order of columns in a
+table within a :class:`.ops.CreateTableOp` directive. This directive, when
+generated by autogenerate, actually holds onto the original :class:`.Table`
+object as the source of its information, so attempting to reorder the
+:attr:`.ops.CreateTableOp.columns` collection will usually have no effect.
+Instead, a new :class:`.ops.CreateTableOp` object may be constructed with the
+new ordering. However, a second issue is that the :class:`.Column` objects
+inside will already be associated with the :class:`.Table` that is from the
+model being autogenerated, meaning they can't be reassigned directly to a new
+:class:`.Table`. To get around this, we can copy all the columns and constraints
+using methods like :meth:`.Column.copy`.
+
+Below we use :class:`.Rewriter` to create a new :class:`.ops.CreateTableOp`
+directive and to copy the :class:`.Column` objects from one into another,
+copying each column or constraint object and applying a new sorting scheme::
+
+ # 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::
+
+ 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 ###
+
Don't emit CREATE TABLE statements for Views
============================================